ninegrid2 6.532.0 → 6.534.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/dist/ai/aiContainer.js +10 -110
- package/dist/bundle.cjs.js +113 -105
- package/dist/bundle.esm.js +113 -105
- package/dist/utils/ninegrid.js +108 -0
- package/package.json +1 -1
- package/src/ai/aiContainer.js +10 -110
- package/src/utils/ninegrid.js +108 -0
package/dist/ai/aiContainer.js
CHANGED
|
@@ -48,7 +48,7 @@ class aiContainer extends HTMLElement
|
|
|
48
48
|
</div>
|
|
49
49
|
<div class="menu">
|
|
50
50
|
<div class="collapse-icon"></div>
|
|
51
|
-
<div class="menu-icon menu-filter
|
|
51
|
+
<div class="menu-icon menu-filter active"></div>
|
|
52
52
|
<div class="menu-icon menu-general"></div>
|
|
53
53
|
<div class="menu-icon menu-setting"></div>
|
|
54
54
|
</div>
|
|
@@ -237,114 +237,11 @@ class aiContainer extends HTMLElement
|
|
|
237
237
|
//}
|
|
238
238
|
};
|
|
239
239
|
|
|
240
|
-
/**
|
|
241
|
-
* Qdrant 필터링 조건에 따라 JSON 배열을 필터링하는 함수입니다.
|
|
242
|
-
*
|
|
243
|
-
* @param {Array<Object>} jsonArray 필터링할 JSON 객체 배열입니다.
|
|
244
|
-
* @param {Object} filter 필터링 조건 객체입니다. Qdrant 필터와 유사한 구조를 가집니다.
|
|
245
|
-
* 예시:
|
|
246
|
-
* {
|
|
247
|
-
* must: [ // 모든 조건이 참이어야 함
|
|
248
|
-
* { key: "field1", match: { value: "some_value" } },
|
|
249
|
-
* { key: "field2", range: { gte: 10, lt: 20 } }
|
|
250
|
-
* ],
|
|
251
|
-
* should: [ // 하나 이상의 조건이 참이어야 함
|
|
252
|
-
* { key: "field3", match: { value: "another_value" } },
|
|
253
|
-
* { key: "field4", match: { any: ["valueA", "valueB"] } }
|
|
254
|
-
* ],
|
|
255
|
-
* must_not: [ // 어떤 조건도 참이 아니어야 함
|
|
256
|
-
* { key: "field5", match: { value: "excluded_value" } }
|
|
257
|
-
* ]
|
|
258
|
-
* }
|
|
259
|
-
* @returns {Array<Object>} 필터링된 JSON 객체 배열입니다.
|
|
260
|
-
*/
|
|
261
|
-
#filterJsonArray = (jsonArray, filter) => {
|
|
262
|
-
if (!jsonArray || !Array.isArray(jsonArray)) {
|
|
263
|
-
console.error("첫 번째 인수는 JSON 배열이어야 합니다.");
|
|
264
|
-
return [];
|
|
265
|
-
}
|
|
266
|
-
if (!filter || typeof filter !== 'object') {
|
|
267
|
-
// 필터 조건이 없거나 유효하지 않으면 원본 배열 반환
|
|
268
|
-
return jsonArray;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
return jsonArray.filter(item => {
|
|
272
|
-
// 'must' 조건 처리: 모든 'must' 조건이 참이어야 합니다.
|
|
273
|
-
if (filter.must && !filter.must.every(condition => this.#evaluateCondition(item, condition))) {
|
|
274
|
-
return false;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
// 'should' 조건 처리: 하나 이상의 'should' 조건이 참이어야 합니다.
|
|
278
|
-
// 'should' 조건이 없으면 이 부분은 건너뜁니다.
|
|
279
|
-
if (filter.should && filter.should.length > 0 && !filter.should.some(condition => this.#evaluateCondition(item, condition))) {
|
|
280
|
-
return false;
|
|
281
|
-
} else if (filter.should && filter.should.length === 0 && (filter.must || filter.must_not)) {
|
|
282
|
-
// 'should'가 비어있고 'must'나 'must_not'가 있으면 'should'는 필터링에 영향 없음.
|
|
283
|
-
// 하지만 'should'만 있고 비어있다면, 사실상 필터링이 안 되는 것과 같으므로 true 반환.
|
|
284
|
-
// 이 로직은 Qdrant의 'should'가 비어있을 때의 동작과 일치하도록 조정될 수 있습니다.
|
|
285
|
-
// 현재는 'should'가 비어있으면 필터링에 영향이 없도록 합니다.
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
// 'must_not' 조건 처리: 어떤 'must_not' 조건도 참이 아니어야 합니다.
|
|
290
|
-
if (filter.must_not && filter.must_not.some(condition => this.#evaluateCondition(item, condition))) {
|
|
291
|
-
return false;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
return true;
|
|
295
|
-
});
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
/**
|
|
299
|
-
* 단일 필터링 조건을 평가하는 헬퍼 함수입니다.
|
|
300
|
-
* @param {Object} item 현재 평가 중인 JSON 객체입니다.
|
|
301
|
-
* @param {Object} condition 평가할 단일 조건입니다. (예: { key: "field1", match: { value: "some_value" } })
|
|
302
|
-
* @returns {boolean} 조건이 참이면 true, 그렇지 않으면 false.
|
|
303
|
-
*/
|
|
304
|
-
#evaluateCondition = (item, condition) => {
|
|
305
|
-
const valueInItem = item[condition.key];
|
|
306
|
-
|
|
307
|
-
if (condition.match) {
|
|
308
|
-
const match = condition.match;
|
|
309
|
-
if (match.value !== undefined) {
|
|
310
|
-
return valueInItem === match.value;
|
|
311
|
-
}
|
|
312
|
-
if (match.any && Array.isArray(match.any)) {
|
|
313
|
-
return match.any.includes(valueInItem);
|
|
314
|
-
}
|
|
315
|
-
if (match.all && Array.isArray(match.all)) {
|
|
316
|
-
// item[condition.key]가 배열이라고 가정
|
|
317
|
-
if (!Array.isArray(valueInItem)) return false;
|
|
318
|
-
return match.all.every(val => valueInItem.includes(val));
|
|
319
|
-
}
|
|
320
|
-
if (match.text !== undefined) {
|
|
321
|
-
// 텍스트 매치는 부분 문자열 일치 또는 정규식 등으로 확장 가능
|
|
322
|
-
// 여기서는 단순 포함 여부로 구현
|
|
323
|
-
return typeof valueInItem === 'string' && valueInItem.includes(match.text);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
if (condition.range) {
|
|
328
|
-
const range = condition.range;
|
|
329
|
-
if (typeof valueInItem !== 'number') return false; // 숫자가 아니면 범위 비교 불가
|
|
330
|
-
|
|
331
|
-
if (range.gte !== undefined && !(valueInItem >= range.gte)) return false;
|
|
332
|
-
if (range.gt !== undefined && !(valueInItem > range.gt)) return false;
|
|
333
|
-
if (range.lte !== undefined && !(valueInItem <= range.lte)) return false;
|
|
334
|
-
if (range.lt !== undefined && !(valueInItem < range.lt)) return false;
|
|
335
|
-
return true;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// 다른 필터 타입 (예: `geo_bounding_box`, `has_id` 등)은 필요에 따라 추가 구현
|
|
339
|
-
// 현재는 `match`와 `range`만 지원합니다.
|
|
340
|
-
|
|
341
|
-
return false; // 지원하지 않는 조건 타입
|
|
342
|
-
}
|
|
343
240
|
|
|
344
241
|
|
|
345
242
|
#q1 = async () => {
|
|
346
243
|
const filter = await this.#generateQdrantFilter();
|
|
347
|
-
const searchResults =
|
|
244
|
+
const searchResults = ninegrid.filter(this.#getData(), filter);
|
|
348
245
|
|
|
349
246
|
await this.#answer(searchResults);
|
|
350
247
|
};
|
|
@@ -361,16 +258,17 @@ class aiContainer extends HTMLElement
|
|
|
361
258
|
const columnInfo = this.#getColumnInfo();
|
|
362
259
|
const uniqueKey = this.#getUniqueKey();
|
|
363
260
|
|
|
364
|
-
console.log(
|
|
261
|
+
console.log(searchResults);
|
|
365
262
|
|
|
366
263
|
if (!searchResults || searchResults.length == 0) {
|
|
367
264
|
elAiChat.add("ai", "관련된 정보가 없습니다.");
|
|
368
265
|
}
|
|
369
266
|
else if (searchResults.length > 100) {
|
|
370
|
-
elAiChat.add("ai", `${searchResults.length}건의 정보를 찾았습니다.`, columnInfo, searchResults.map(item => item.payload), uniqueKey);
|
|
267
|
+
//elAiChat.add("ai", `${searchResults.length}건의 정보를 찾았습니다.`, columnInfo, searchResults.map(item => item.payload), uniqueKey);
|
|
268
|
+
elAiChat.add("ai", `${searchResults.length}건의 정보를 찾았습니다.`, columnInfo, searchResults, uniqueKey);
|
|
371
269
|
}
|
|
372
270
|
else {
|
|
373
|
-
let arr = searchResults.map(item => item.payload);
|
|
271
|
+
//let arr = searchResults.map(item => item.payload);
|
|
374
272
|
let contextText = `당신은 주어진 정보를 참고하여 답변하는 AI 입니다. 주어진 '정보'를 바탕으로 데이타를 분석해줘. 데이타는 "context" 항목에 있어. 제공될 데이터는 CSV 형식이며, 첫 번째 줄은 컬럼명입니다. 이전에 너가 찾아준 데이타를 다시 보내는거니깐 첫 줄에는 "${arr.length}건을 찾았습니다." 라고 답변을 달아줘.\n\ncontext: `;
|
|
375
273
|
|
|
376
274
|
let contextText1 = `당신은 주어진 데이터를 분석하고 핵심 인사이트를 도출하는 전문 데이터 분석가입니다.
|
|
@@ -398,7 +296,9 @@ class aiContainer extends HTMLElement
|
|
|
398
296
|
});
|
|
399
297
|
contextText += "\n";
|
|
400
298
|
|
|
401
|
-
for (const o of
|
|
299
|
+
for (const o of searchResults) {
|
|
300
|
+
|
|
301
|
+
console.log(o);
|
|
402
302
|
columnInfo.forEach(info => {
|
|
403
303
|
contextText += `${o[info.name]}\t`;
|
|
404
304
|
});
|
|
@@ -476,7 +376,7 @@ class aiContainer extends HTMLElement
|
|
|
476
376
|
await this.#q2();
|
|
477
377
|
}
|
|
478
378
|
} catch (error) {
|
|
479
|
-
|
|
379
|
+
console.error(error);
|
|
480
380
|
elAiChat.add("ai", error);
|
|
481
381
|
}
|
|
482
382
|
|
package/dist/bundle.cjs.js
CHANGED
|
@@ -11530,6 +11530,109 @@ class ninegrid {
|
|
|
11530
11530
|
return nxAlertPopup.alert(message, title, options);
|
|
11531
11531
|
}
|
|
11532
11532
|
|
|
11533
|
+
|
|
11534
|
+
/**
|
|
11535
|
+
* Qdrant 필터링 조건에 따라 JSON 배열을 필터링하는 함수입니다.
|
|
11536
|
+
*
|
|
11537
|
+
* @param {Array<Object>} jsonArray 필터링할 JSON 객체 배열입니다.
|
|
11538
|
+
* @param {Object} filter 필터링 조건 객체입니다. Qdrant 필터와 유사한 구조를 가집니다.
|
|
11539
|
+
* 예시:
|
|
11540
|
+
* {
|
|
11541
|
+
* must: [ // 모든 조건이 참이어야 함
|
|
11542
|
+
* { key: "field1", match: { value: "some_value" } },
|
|
11543
|
+
* { key: "field2", range: { gte: 10, lt: 20 } }
|
|
11544
|
+
* ],
|
|
11545
|
+
* should: [ // 하나 이상의 조건이 참이어야 함
|
|
11546
|
+
* { key: "field3", match: { value: "another_value" } },
|
|
11547
|
+
* { key: "field4", match: { any: ["valueA", "valueB"] } }
|
|
11548
|
+
* ],
|
|
11549
|
+
* must_not: [ // 어떤 조건도 참이 아니어야 함
|
|
11550
|
+
* { key: "field5", match: { value: "excluded_value" } }
|
|
11551
|
+
* ]
|
|
11552
|
+
* }
|
|
11553
|
+
* @returns {Array<Object>} 필터링된 JSON 객체 배열입니다.
|
|
11554
|
+
*/
|
|
11555
|
+
static filter = (jsonArray, filter) => {
|
|
11556
|
+
/**
|
|
11557
|
+
* 단일 필터링 조건을 평가하는 헬퍼 함수입니다.
|
|
11558
|
+
* @param {Object} item 현재 평가 중인 JSON 객체입니다.
|
|
11559
|
+
* @param {Object} condition 평가할 단일 조건입니다. (예: { key: "field1", match: { value: "some_value" } })
|
|
11560
|
+
* @returns {boolean} 조건이 참이면 true, 그렇지 않으면 false.
|
|
11561
|
+
*/
|
|
11562
|
+
const evaluateCondition = (item, condition) => {
|
|
11563
|
+
const valueInItem = item[condition.key];
|
|
11564
|
+
|
|
11565
|
+
if (condition.match) {
|
|
11566
|
+
const match = condition.match;
|
|
11567
|
+
if (match.value !== undefined) {
|
|
11568
|
+
return valueInItem === match.value;
|
|
11569
|
+
}
|
|
11570
|
+
if (match.any && Array.isArray(match.any)) {
|
|
11571
|
+
return match.any.includes(valueInItem);
|
|
11572
|
+
}
|
|
11573
|
+
if (match.all && Array.isArray(match.all)) {
|
|
11574
|
+
// item[condition.key]가 배열이라고 가정
|
|
11575
|
+
if (!Array.isArray(valueInItem)) return false;
|
|
11576
|
+
return match.all.every(val => valueInItem.includes(val));
|
|
11577
|
+
}
|
|
11578
|
+
if (match.text !== undefined) {
|
|
11579
|
+
// 텍스트 매치는 부분 문자열 일치 또는 정규식 등으로 확장 가능
|
|
11580
|
+
// 여기서는 단순 포함 여부로 구현
|
|
11581
|
+
return typeof valueInItem === 'string' && valueInItem.includes(match.text);
|
|
11582
|
+
}
|
|
11583
|
+
}
|
|
11584
|
+
|
|
11585
|
+
if (condition.range) {
|
|
11586
|
+
const range = condition.range;
|
|
11587
|
+
if (typeof valueInItem !== 'number') return false; // 숫자가 아니면 범위 비교 불가
|
|
11588
|
+
|
|
11589
|
+
if (range.gte !== undefined && !(valueInItem >= range.gte)) return false;
|
|
11590
|
+
if (range.gt !== undefined && !(valueInItem > range.gt)) return false;
|
|
11591
|
+
if (range.lte !== undefined && !(valueInItem <= range.lte)) return false;
|
|
11592
|
+
if (range.lt !== undefined && !(valueInItem < range.lt)) return false;
|
|
11593
|
+
return true;
|
|
11594
|
+
}
|
|
11595
|
+
|
|
11596
|
+
// 다른 필터 타입 (예: `geo_bounding_box`, `has_id` 등)은 필요에 따라 추가 구현
|
|
11597
|
+
// 현재는 `match`와 `range`만 지원합니다.
|
|
11598
|
+
|
|
11599
|
+
return false; // 지원하지 않는 조건 타입
|
|
11600
|
+
};
|
|
11601
|
+
if (!jsonArray || !Array.isArray(jsonArray)) {
|
|
11602
|
+
console.error("첫 번째 인수는 JSON 배열이어야 합니다.");
|
|
11603
|
+
return [];
|
|
11604
|
+
}
|
|
11605
|
+
if (!filter || typeof filter !== 'object') {
|
|
11606
|
+
// 필터 조건이 없거나 유효하지 않으면 원본 배열 반환
|
|
11607
|
+
return jsonArray;
|
|
11608
|
+
}
|
|
11609
|
+
|
|
11610
|
+
return jsonArray.filter(item => {
|
|
11611
|
+
// 'must' 조건 처리: 모든 'must' 조건이 참이어야 합니다.
|
|
11612
|
+
if (filter.must && !filter.must.every(condition => evaluateCondition(item, condition))) {
|
|
11613
|
+
return false;
|
|
11614
|
+
}
|
|
11615
|
+
|
|
11616
|
+
// 'should' 조건 처리: 하나 이상의 'should' 조건이 참이어야 합니다.
|
|
11617
|
+
// 'should' 조건이 없으면 이 부분은 건너뜁니다.
|
|
11618
|
+
if (filter.should && filter.should.length > 0 && !filter.should.some(condition => evaluateCondition(item, condition))) {
|
|
11619
|
+
return false;
|
|
11620
|
+
} else if (filter.should && filter.should.length === 0 && (filter.must || filter.must_not)) ;
|
|
11621
|
+
|
|
11622
|
+
|
|
11623
|
+
// 'must_not' 조건 처리: 어떤 'must_not' 조건도 참이 아니어야 합니다.
|
|
11624
|
+
if (filter.must_not && filter.must_not.some(condition => evaluateCondition(item, condition))) {
|
|
11625
|
+
return false;
|
|
11626
|
+
}
|
|
11627
|
+
|
|
11628
|
+
return true;
|
|
11629
|
+
});
|
|
11630
|
+
}
|
|
11631
|
+
|
|
11632
|
+
|
|
11633
|
+
|
|
11634
|
+
|
|
11635
|
+
|
|
11533
11636
|
static j = {
|
|
11534
11637
|
copyEvents: (source, target) => {
|
|
11535
11638
|
const events = getEventListeners(source);
|
|
@@ -54142,7 +54245,7 @@ class aiContainer extends HTMLElement
|
|
|
54142
54245
|
</div>
|
|
54143
54246
|
<div class="menu">
|
|
54144
54247
|
<div class="collapse-icon"></div>
|
|
54145
|
-
<div class="menu-icon menu-filter
|
|
54248
|
+
<div class="menu-icon menu-filter active"></div>
|
|
54146
54249
|
<div class="menu-icon menu-general"></div>
|
|
54147
54250
|
<div class="menu-icon menu-setting"></div>
|
|
54148
54251
|
</div>
|
|
@@ -54327,109 +54430,11 @@ class aiContainer extends HTMLElement
|
|
|
54327
54430
|
//}
|
|
54328
54431
|
};
|
|
54329
54432
|
|
|
54330
|
-
/**
|
|
54331
|
-
* Qdrant 필터링 조건에 따라 JSON 배열을 필터링하는 함수입니다.
|
|
54332
|
-
*
|
|
54333
|
-
* @param {Array<Object>} jsonArray 필터링할 JSON 객체 배열입니다.
|
|
54334
|
-
* @param {Object} filter 필터링 조건 객체입니다. Qdrant 필터와 유사한 구조를 가집니다.
|
|
54335
|
-
* 예시:
|
|
54336
|
-
* {
|
|
54337
|
-
* must: [ // 모든 조건이 참이어야 함
|
|
54338
|
-
* { key: "field1", match: { value: "some_value" } },
|
|
54339
|
-
* { key: "field2", range: { gte: 10, lt: 20 } }
|
|
54340
|
-
* ],
|
|
54341
|
-
* should: [ // 하나 이상의 조건이 참이어야 함
|
|
54342
|
-
* { key: "field3", match: { value: "another_value" } },
|
|
54343
|
-
* { key: "field4", match: { any: ["valueA", "valueB"] } }
|
|
54344
|
-
* ],
|
|
54345
|
-
* must_not: [ // 어떤 조건도 참이 아니어야 함
|
|
54346
|
-
* { key: "field5", match: { value: "excluded_value" } }
|
|
54347
|
-
* ]
|
|
54348
|
-
* }
|
|
54349
|
-
* @returns {Array<Object>} 필터링된 JSON 객체 배열입니다.
|
|
54350
|
-
*/
|
|
54351
|
-
#filterJsonArray = (jsonArray, filter) => {
|
|
54352
|
-
if (!jsonArray || !Array.isArray(jsonArray)) {
|
|
54353
|
-
console.error("첫 번째 인수는 JSON 배열이어야 합니다.");
|
|
54354
|
-
return [];
|
|
54355
|
-
}
|
|
54356
|
-
if (!filter || typeof filter !== 'object') {
|
|
54357
|
-
// 필터 조건이 없거나 유효하지 않으면 원본 배열 반환
|
|
54358
|
-
return jsonArray;
|
|
54359
|
-
}
|
|
54360
|
-
|
|
54361
|
-
return jsonArray.filter(item => {
|
|
54362
|
-
// 'must' 조건 처리: 모든 'must' 조건이 참이어야 합니다.
|
|
54363
|
-
if (filter.must && !filter.must.every(condition => this.#evaluateCondition(item, condition))) {
|
|
54364
|
-
return false;
|
|
54365
|
-
}
|
|
54366
|
-
|
|
54367
|
-
// 'should' 조건 처리: 하나 이상의 'should' 조건이 참이어야 합니다.
|
|
54368
|
-
// 'should' 조건이 없으면 이 부분은 건너뜁니다.
|
|
54369
|
-
if (filter.should && filter.should.length > 0 && !filter.should.some(condition => this.#evaluateCondition(item, condition))) {
|
|
54370
|
-
return false;
|
|
54371
|
-
} else if (filter.should && filter.should.length === 0 && (filter.must || filter.must_not)) ;
|
|
54372
|
-
|
|
54373
|
-
|
|
54374
|
-
// 'must_not' 조건 처리: 어떤 'must_not' 조건도 참이 아니어야 합니다.
|
|
54375
|
-
if (filter.must_not && filter.must_not.some(condition => this.#evaluateCondition(item, condition))) {
|
|
54376
|
-
return false;
|
|
54377
|
-
}
|
|
54378
|
-
|
|
54379
|
-
return true;
|
|
54380
|
-
});
|
|
54381
|
-
}
|
|
54382
|
-
|
|
54383
|
-
/**
|
|
54384
|
-
* 단일 필터링 조건을 평가하는 헬퍼 함수입니다.
|
|
54385
|
-
* @param {Object} item 현재 평가 중인 JSON 객체입니다.
|
|
54386
|
-
* @param {Object} condition 평가할 단일 조건입니다. (예: { key: "field1", match: { value: "some_value" } })
|
|
54387
|
-
* @returns {boolean} 조건이 참이면 true, 그렇지 않으면 false.
|
|
54388
|
-
*/
|
|
54389
|
-
#evaluateCondition = (item, condition) => {
|
|
54390
|
-
const valueInItem = item[condition.key];
|
|
54391
|
-
|
|
54392
|
-
if (condition.match) {
|
|
54393
|
-
const match = condition.match;
|
|
54394
|
-
if (match.value !== undefined) {
|
|
54395
|
-
return valueInItem === match.value;
|
|
54396
|
-
}
|
|
54397
|
-
if (match.any && Array.isArray(match.any)) {
|
|
54398
|
-
return match.any.includes(valueInItem);
|
|
54399
|
-
}
|
|
54400
|
-
if (match.all && Array.isArray(match.all)) {
|
|
54401
|
-
// item[condition.key]가 배열이라고 가정
|
|
54402
|
-
if (!Array.isArray(valueInItem)) return false;
|
|
54403
|
-
return match.all.every(val => valueInItem.includes(val));
|
|
54404
|
-
}
|
|
54405
|
-
if (match.text !== undefined) {
|
|
54406
|
-
// 텍스트 매치는 부분 문자열 일치 또는 정규식 등으로 확장 가능
|
|
54407
|
-
// 여기서는 단순 포함 여부로 구현
|
|
54408
|
-
return typeof valueInItem === 'string' && valueInItem.includes(match.text);
|
|
54409
|
-
}
|
|
54410
|
-
}
|
|
54411
|
-
|
|
54412
|
-
if (condition.range) {
|
|
54413
|
-
const range = condition.range;
|
|
54414
|
-
if (typeof valueInItem !== 'number') return false; // 숫자가 아니면 범위 비교 불가
|
|
54415
|
-
|
|
54416
|
-
if (range.gte !== undefined && !(valueInItem >= range.gte)) return false;
|
|
54417
|
-
if (range.gt !== undefined && !(valueInItem > range.gt)) return false;
|
|
54418
|
-
if (range.lte !== undefined && !(valueInItem <= range.lte)) return false;
|
|
54419
|
-
if (range.lt !== undefined && !(valueInItem < range.lt)) return false;
|
|
54420
|
-
return true;
|
|
54421
|
-
}
|
|
54422
|
-
|
|
54423
|
-
// 다른 필터 타입 (예: `geo_bounding_box`, `has_id` 등)은 필요에 따라 추가 구현
|
|
54424
|
-
// 현재는 `match`와 `range`만 지원합니다.
|
|
54425
|
-
|
|
54426
|
-
return false; // 지원하지 않는 조건 타입
|
|
54427
|
-
}
|
|
54428
54433
|
|
|
54429
54434
|
|
|
54430
54435
|
#q1 = async () => {
|
|
54431
54436
|
const filter = await this.#generateQdrantFilter();
|
|
54432
|
-
const searchResults =
|
|
54437
|
+
const searchResults = ninegrid.filter(this.#getData(), filter);
|
|
54433
54438
|
|
|
54434
54439
|
await this.#answer(searchResults);
|
|
54435
54440
|
};
|
|
@@ -54446,16 +54451,17 @@ class aiContainer extends HTMLElement
|
|
|
54446
54451
|
const columnInfo = this.#getColumnInfo();
|
|
54447
54452
|
const uniqueKey = this.#getUniqueKey();
|
|
54448
54453
|
|
|
54449
|
-
console.log(
|
|
54454
|
+
console.log(searchResults);
|
|
54450
54455
|
|
|
54451
54456
|
if (!searchResults || searchResults.length == 0) {
|
|
54452
54457
|
elAiChat.add("ai", "관련된 정보가 없습니다.");
|
|
54453
54458
|
}
|
|
54454
54459
|
else if (searchResults.length > 100) {
|
|
54455
|
-
elAiChat.add("ai", `${searchResults.length}건의 정보를 찾았습니다.`, columnInfo, searchResults.map(item => item.payload), uniqueKey);
|
|
54460
|
+
//elAiChat.add("ai", `${searchResults.length}건의 정보를 찾았습니다.`, columnInfo, searchResults.map(item => item.payload), uniqueKey);
|
|
54461
|
+
elAiChat.add("ai", `${searchResults.length}건의 정보를 찾았습니다.`, columnInfo, searchResults, uniqueKey);
|
|
54456
54462
|
}
|
|
54457
54463
|
else {
|
|
54458
|
-
let arr = searchResults.map(item => item.payload);
|
|
54464
|
+
//let arr = searchResults.map(item => item.payload);
|
|
54459
54465
|
let contextText = `당신은 주어진 정보를 참고하여 답변하는 AI 입니다. 주어진 '정보'를 바탕으로 데이타를 분석해줘. 데이타는 "context" 항목에 있어. 제공될 데이터는 CSV 형식이며, 첫 번째 줄은 컬럼명입니다. 이전에 너가 찾아준 데이타를 다시 보내는거니깐 첫 줄에는 "${arr.length}건을 찾았습니다." 라고 답변을 달아줘.\n\ncontext: `;
|
|
54460
54466
|
|
|
54461
54467
|
columnInfo.forEach(info => {
|
|
@@ -54463,7 +54469,9 @@ class aiContainer extends HTMLElement
|
|
|
54463
54469
|
});
|
|
54464
54470
|
contextText += "\n";
|
|
54465
54471
|
|
|
54466
|
-
for (const o of
|
|
54472
|
+
for (const o of searchResults) {
|
|
54473
|
+
|
|
54474
|
+
console.log(o);
|
|
54467
54475
|
columnInfo.forEach(info => {
|
|
54468
54476
|
contextText += `${o[info.name]}\t`;
|
|
54469
54477
|
});
|
|
@@ -54540,7 +54548,7 @@ class aiContainer extends HTMLElement
|
|
|
54540
54548
|
await this.#q2();
|
|
54541
54549
|
}
|
|
54542
54550
|
} catch (error) {
|
|
54543
|
-
|
|
54551
|
+
console.error(error);
|
|
54544
54552
|
elAiChat.add("ai", error);
|
|
54545
54553
|
}
|
|
54546
54554
|
|
package/dist/bundle.esm.js
CHANGED
|
@@ -11528,6 +11528,109 @@ class ninegrid {
|
|
|
11528
11528
|
return nxAlertPopup.alert(message, title, options);
|
|
11529
11529
|
}
|
|
11530
11530
|
|
|
11531
|
+
|
|
11532
|
+
/**
|
|
11533
|
+
* Qdrant 필터링 조건에 따라 JSON 배열을 필터링하는 함수입니다.
|
|
11534
|
+
*
|
|
11535
|
+
* @param {Array<Object>} jsonArray 필터링할 JSON 객체 배열입니다.
|
|
11536
|
+
* @param {Object} filter 필터링 조건 객체입니다. Qdrant 필터와 유사한 구조를 가집니다.
|
|
11537
|
+
* 예시:
|
|
11538
|
+
* {
|
|
11539
|
+
* must: [ // 모든 조건이 참이어야 함
|
|
11540
|
+
* { key: "field1", match: { value: "some_value" } },
|
|
11541
|
+
* { key: "field2", range: { gte: 10, lt: 20 } }
|
|
11542
|
+
* ],
|
|
11543
|
+
* should: [ // 하나 이상의 조건이 참이어야 함
|
|
11544
|
+
* { key: "field3", match: { value: "another_value" } },
|
|
11545
|
+
* { key: "field4", match: { any: ["valueA", "valueB"] } }
|
|
11546
|
+
* ],
|
|
11547
|
+
* must_not: [ // 어떤 조건도 참이 아니어야 함
|
|
11548
|
+
* { key: "field5", match: { value: "excluded_value" } }
|
|
11549
|
+
* ]
|
|
11550
|
+
* }
|
|
11551
|
+
* @returns {Array<Object>} 필터링된 JSON 객체 배열입니다.
|
|
11552
|
+
*/
|
|
11553
|
+
static filter = (jsonArray, filter) => {
|
|
11554
|
+
/**
|
|
11555
|
+
* 단일 필터링 조건을 평가하는 헬퍼 함수입니다.
|
|
11556
|
+
* @param {Object} item 현재 평가 중인 JSON 객체입니다.
|
|
11557
|
+
* @param {Object} condition 평가할 단일 조건입니다. (예: { key: "field1", match: { value: "some_value" } })
|
|
11558
|
+
* @returns {boolean} 조건이 참이면 true, 그렇지 않으면 false.
|
|
11559
|
+
*/
|
|
11560
|
+
const evaluateCondition = (item, condition) => {
|
|
11561
|
+
const valueInItem = item[condition.key];
|
|
11562
|
+
|
|
11563
|
+
if (condition.match) {
|
|
11564
|
+
const match = condition.match;
|
|
11565
|
+
if (match.value !== undefined) {
|
|
11566
|
+
return valueInItem === match.value;
|
|
11567
|
+
}
|
|
11568
|
+
if (match.any && Array.isArray(match.any)) {
|
|
11569
|
+
return match.any.includes(valueInItem);
|
|
11570
|
+
}
|
|
11571
|
+
if (match.all && Array.isArray(match.all)) {
|
|
11572
|
+
// item[condition.key]가 배열이라고 가정
|
|
11573
|
+
if (!Array.isArray(valueInItem)) return false;
|
|
11574
|
+
return match.all.every(val => valueInItem.includes(val));
|
|
11575
|
+
}
|
|
11576
|
+
if (match.text !== undefined) {
|
|
11577
|
+
// 텍스트 매치는 부분 문자열 일치 또는 정규식 등으로 확장 가능
|
|
11578
|
+
// 여기서는 단순 포함 여부로 구현
|
|
11579
|
+
return typeof valueInItem === 'string' && valueInItem.includes(match.text);
|
|
11580
|
+
}
|
|
11581
|
+
}
|
|
11582
|
+
|
|
11583
|
+
if (condition.range) {
|
|
11584
|
+
const range = condition.range;
|
|
11585
|
+
if (typeof valueInItem !== 'number') return false; // 숫자가 아니면 범위 비교 불가
|
|
11586
|
+
|
|
11587
|
+
if (range.gte !== undefined && !(valueInItem >= range.gte)) return false;
|
|
11588
|
+
if (range.gt !== undefined && !(valueInItem > range.gt)) return false;
|
|
11589
|
+
if (range.lte !== undefined && !(valueInItem <= range.lte)) return false;
|
|
11590
|
+
if (range.lt !== undefined && !(valueInItem < range.lt)) return false;
|
|
11591
|
+
return true;
|
|
11592
|
+
}
|
|
11593
|
+
|
|
11594
|
+
// 다른 필터 타입 (예: `geo_bounding_box`, `has_id` 등)은 필요에 따라 추가 구현
|
|
11595
|
+
// 현재는 `match`와 `range`만 지원합니다.
|
|
11596
|
+
|
|
11597
|
+
return false; // 지원하지 않는 조건 타입
|
|
11598
|
+
};
|
|
11599
|
+
if (!jsonArray || !Array.isArray(jsonArray)) {
|
|
11600
|
+
console.error("첫 번째 인수는 JSON 배열이어야 합니다.");
|
|
11601
|
+
return [];
|
|
11602
|
+
}
|
|
11603
|
+
if (!filter || typeof filter !== 'object') {
|
|
11604
|
+
// 필터 조건이 없거나 유효하지 않으면 원본 배열 반환
|
|
11605
|
+
return jsonArray;
|
|
11606
|
+
}
|
|
11607
|
+
|
|
11608
|
+
return jsonArray.filter(item => {
|
|
11609
|
+
// 'must' 조건 처리: 모든 'must' 조건이 참이어야 합니다.
|
|
11610
|
+
if (filter.must && !filter.must.every(condition => evaluateCondition(item, condition))) {
|
|
11611
|
+
return false;
|
|
11612
|
+
}
|
|
11613
|
+
|
|
11614
|
+
// 'should' 조건 처리: 하나 이상의 'should' 조건이 참이어야 합니다.
|
|
11615
|
+
// 'should' 조건이 없으면 이 부분은 건너뜁니다.
|
|
11616
|
+
if (filter.should && filter.should.length > 0 && !filter.should.some(condition => evaluateCondition(item, condition))) {
|
|
11617
|
+
return false;
|
|
11618
|
+
} else if (filter.should && filter.should.length === 0 && (filter.must || filter.must_not)) ;
|
|
11619
|
+
|
|
11620
|
+
|
|
11621
|
+
// 'must_not' 조건 처리: 어떤 'must_not' 조건도 참이 아니어야 합니다.
|
|
11622
|
+
if (filter.must_not && filter.must_not.some(condition => evaluateCondition(item, condition))) {
|
|
11623
|
+
return false;
|
|
11624
|
+
}
|
|
11625
|
+
|
|
11626
|
+
return true;
|
|
11627
|
+
});
|
|
11628
|
+
}
|
|
11629
|
+
|
|
11630
|
+
|
|
11631
|
+
|
|
11632
|
+
|
|
11633
|
+
|
|
11531
11634
|
static j = {
|
|
11532
11635
|
copyEvents: (source, target) => {
|
|
11533
11636
|
const events = getEventListeners(source);
|
|
@@ -54140,7 +54243,7 @@ class aiContainer extends HTMLElement
|
|
|
54140
54243
|
</div>
|
|
54141
54244
|
<div class="menu">
|
|
54142
54245
|
<div class="collapse-icon"></div>
|
|
54143
|
-
<div class="menu-icon menu-filter
|
|
54246
|
+
<div class="menu-icon menu-filter active"></div>
|
|
54144
54247
|
<div class="menu-icon menu-general"></div>
|
|
54145
54248
|
<div class="menu-icon menu-setting"></div>
|
|
54146
54249
|
</div>
|
|
@@ -54325,109 +54428,11 @@ class aiContainer extends HTMLElement
|
|
|
54325
54428
|
//}
|
|
54326
54429
|
};
|
|
54327
54430
|
|
|
54328
|
-
/**
|
|
54329
|
-
* Qdrant 필터링 조건에 따라 JSON 배열을 필터링하는 함수입니다.
|
|
54330
|
-
*
|
|
54331
|
-
* @param {Array<Object>} jsonArray 필터링할 JSON 객체 배열입니다.
|
|
54332
|
-
* @param {Object} filter 필터링 조건 객체입니다. Qdrant 필터와 유사한 구조를 가집니다.
|
|
54333
|
-
* 예시:
|
|
54334
|
-
* {
|
|
54335
|
-
* must: [ // 모든 조건이 참이어야 함
|
|
54336
|
-
* { key: "field1", match: { value: "some_value" } },
|
|
54337
|
-
* { key: "field2", range: { gte: 10, lt: 20 } }
|
|
54338
|
-
* ],
|
|
54339
|
-
* should: [ // 하나 이상의 조건이 참이어야 함
|
|
54340
|
-
* { key: "field3", match: { value: "another_value" } },
|
|
54341
|
-
* { key: "field4", match: { any: ["valueA", "valueB"] } }
|
|
54342
|
-
* ],
|
|
54343
|
-
* must_not: [ // 어떤 조건도 참이 아니어야 함
|
|
54344
|
-
* { key: "field5", match: { value: "excluded_value" } }
|
|
54345
|
-
* ]
|
|
54346
|
-
* }
|
|
54347
|
-
* @returns {Array<Object>} 필터링된 JSON 객체 배열입니다.
|
|
54348
|
-
*/
|
|
54349
|
-
#filterJsonArray = (jsonArray, filter) => {
|
|
54350
|
-
if (!jsonArray || !Array.isArray(jsonArray)) {
|
|
54351
|
-
console.error("첫 번째 인수는 JSON 배열이어야 합니다.");
|
|
54352
|
-
return [];
|
|
54353
|
-
}
|
|
54354
|
-
if (!filter || typeof filter !== 'object') {
|
|
54355
|
-
// 필터 조건이 없거나 유효하지 않으면 원본 배열 반환
|
|
54356
|
-
return jsonArray;
|
|
54357
|
-
}
|
|
54358
|
-
|
|
54359
|
-
return jsonArray.filter(item => {
|
|
54360
|
-
// 'must' 조건 처리: 모든 'must' 조건이 참이어야 합니다.
|
|
54361
|
-
if (filter.must && !filter.must.every(condition => this.#evaluateCondition(item, condition))) {
|
|
54362
|
-
return false;
|
|
54363
|
-
}
|
|
54364
|
-
|
|
54365
|
-
// 'should' 조건 처리: 하나 이상의 'should' 조건이 참이어야 합니다.
|
|
54366
|
-
// 'should' 조건이 없으면 이 부분은 건너뜁니다.
|
|
54367
|
-
if (filter.should && filter.should.length > 0 && !filter.should.some(condition => this.#evaluateCondition(item, condition))) {
|
|
54368
|
-
return false;
|
|
54369
|
-
} else if (filter.should && filter.should.length === 0 && (filter.must || filter.must_not)) ;
|
|
54370
|
-
|
|
54371
|
-
|
|
54372
|
-
// 'must_not' 조건 처리: 어떤 'must_not' 조건도 참이 아니어야 합니다.
|
|
54373
|
-
if (filter.must_not && filter.must_not.some(condition => this.#evaluateCondition(item, condition))) {
|
|
54374
|
-
return false;
|
|
54375
|
-
}
|
|
54376
|
-
|
|
54377
|
-
return true;
|
|
54378
|
-
});
|
|
54379
|
-
}
|
|
54380
|
-
|
|
54381
|
-
/**
|
|
54382
|
-
* 단일 필터링 조건을 평가하는 헬퍼 함수입니다.
|
|
54383
|
-
* @param {Object} item 현재 평가 중인 JSON 객체입니다.
|
|
54384
|
-
* @param {Object} condition 평가할 단일 조건입니다. (예: { key: "field1", match: { value: "some_value" } })
|
|
54385
|
-
* @returns {boolean} 조건이 참이면 true, 그렇지 않으면 false.
|
|
54386
|
-
*/
|
|
54387
|
-
#evaluateCondition = (item, condition) => {
|
|
54388
|
-
const valueInItem = item[condition.key];
|
|
54389
|
-
|
|
54390
|
-
if (condition.match) {
|
|
54391
|
-
const match = condition.match;
|
|
54392
|
-
if (match.value !== undefined) {
|
|
54393
|
-
return valueInItem === match.value;
|
|
54394
|
-
}
|
|
54395
|
-
if (match.any && Array.isArray(match.any)) {
|
|
54396
|
-
return match.any.includes(valueInItem);
|
|
54397
|
-
}
|
|
54398
|
-
if (match.all && Array.isArray(match.all)) {
|
|
54399
|
-
// item[condition.key]가 배열이라고 가정
|
|
54400
|
-
if (!Array.isArray(valueInItem)) return false;
|
|
54401
|
-
return match.all.every(val => valueInItem.includes(val));
|
|
54402
|
-
}
|
|
54403
|
-
if (match.text !== undefined) {
|
|
54404
|
-
// 텍스트 매치는 부분 문자열 일치 또는 정규식 등으로 확장 가능
|
|
54405
|
-
// 여기서는 단순 포함 여부로 구현
|
|
54406
|
-
return typeof valueInItem === 'string' && valueInItem.includes(match.text);
|
|
54407
|
-
}
|
|
54408
|
-
}
|
|
54409
|
-
|
|
54410
|
-
if (condition.range) {
|
|
54411
|
-
const range = condition.range;
|
|
54412
|
-
if (typeof valueInItem !== 'number') return false; // 숫자가 아니면 범위 비교 불가
|
|
54413
|
-
|
|
54414
|
-
if (range.gte !== undefined && !(valueInItem >= range.gte)) return false;
|
|
54415
|
-
if (range.gt !== undefined && !(valueInItem > range.gt)) return false;
|
|
54416
|
-
if (range.lte !== undefined && !(valueInItem <= range.lte)) return false;
|
|
54417
|
-
if (range.lt !== undefined && !(valueInItem < range.lt)) return false;
|
|
54418
|
-
return true;
|
|
54419
|
-
}
|
|
54420
|
-
|
|
54421
|
-
// 다른 필터 타입 (예: `geo_bounding_box`, `has_id` 등)은 필요에 따라 추가 구현
|
|
54422
|
-
// 현재는 `match`와 `range`만 지원합니다.
|
|
54423
|
-
|
|
54424
|
-
return false; // 지원하지 않는 조건 타입
|
|
54425
|
-
}
|
|
54426
54431
|
|
|
54427
54432
|
|
|
54428
54433
|
#q1 = async () => {
|
|
54429
54434
|
const filter = await this.#generateQdrantFilter();
|
|
54430
|
-
const searchResults =
|
|
54435
|
+
const searchResults = ninegrid.filter(this.#getData(), filter);
|
|
54431
54436
|
|
|
54432
54437
|
await this.#answer(searchResults);
|
|
54433
54438
|
};
|
|
@@ -54444,16 +54449,17 @@ class aiContainer extends HTMLElement
|
|
|
54444
54449
|
const columnInfo = this.#getColumnInfo();
|
|
54445
54450
|
const uniqueKey = this.#getUniqueKey();
|
|
54446
54451
|
|
|
54447
|
-
console.log(
|
|
54452
|
+
console.log(searchResults);
|
|
54448
54453
|
|
|
54449
54454
|
if (!searchResults || searchResults.length == 0) {
|
|
54450
54455
|
elAiChat.add("ai", "관련된 정보가 없습니다.");
|
|
54451
54456
|
}
|
|
54452
54457
|
else if (searchResults.length > 100) {
|
|
54453
|
-
elAiChat.add("ai", `${searchResults.length}건의 정보를 찾았습니다.`, columnInfo, searchResults.map(item => item.payload), uniqueKey);
|
|
54458
|
+
//elAiChat.add("ai", `${searchResults.length}건의 정보를 찾았습니다.`, columnInfo, searchResults.map(item => item.payload), uniqueKey);
|
|
54459
|
+
elAiChat.add("ai", `${searchResults.length}건의 정보를 찾았습니다.`, columnInfo, searchResults, uniqueKey);
|
|
54454
54460
|
}
|
|
54455
54461
|
else {
|
|
54456
|
-
let arr = searchResults.map(item => item.payload);
|
|
54462
|
+
//let arr = searchResults.map(item => item.payload);
|
|
54457
54463
|
let contextText = `당신은 주어진 정보를 참고하여 답변하는 AI 입니다. 주어진 '정보'를 바탕으로 데이타를 분석해줘. 데이타는 "context" 항목에 있어. 제공될 데이터는 CSV 형식이며, 첫 번째 줄은 컬럼명입니다. 이전에 너가 찾아준 데이타를 다시 보내는거니깐 첫 줄에는 "${arr.length}건을 찾았습니다." 라고 답변을 달아줘.\n\ncontext: `;
|
|
54458
54464
|
|
|
54459
54465
|
columnInfo.forEach(info => {
|
|
@@ -54461,7 +54467,9 @@ class aiContainer extends HTMLElement
|
|
|
54461
54467
|
});
|
|
54462
54468
|
contextText += "\n";
|
|
54463
54469
|
|
|
54464
|
-
for (const o of
|
|
54470
|
+
for (const o of searchResults) {
|
|
54471
|
+
|
|
54472
|
+
console.log(o);
|
|
54465
54473
|
columnInfo.forEach(info => {
|
|
54466
54474
|
contextText += `${o[info.name]}\t`;
|
|
54467
54475
|
});
|
|
@@ -54538,7 +54546,7 @@ class aiContainer extends HTMLElement
|
|
|
54538
54546
|
await this.#q2();
|
|
54539
54547
|
}
|
|
54540
54548
|
} catch (error) {
|
|
54541
|
-
|
|
54549
|
+
console.error(error);
|
|
54542
54550
|
elAiChat.add("ai", error);
|
|
54543
54551
|
}
|
|
54544
54552
|
|
package/dist/utils/ninegrid.js
CHANGED
|
@@ -690,6 +690,114 @@ export class ninegrid {
|
|
|
690
690
|
return nxAlertPopup.alert(message, title, options);
|
|
691
691
|
}
|
|
692
692
|
|
|
693
|
+
|
|
694
|
+
/**
|
|
695
|
+
* Qdrant 필터링 조건에 따라 JSON 배열을 필터링하는 함수입니다.
|
|
696
|
+
*
|
|
697
|
+
* @param {Array<Object>} jsonArray 필터링할 JSON 객체 배열입니다.
|
|
698
|
+
* @param {Object} filter 필터링 조건 객체입니다. Qdrant 필터와 유사한 구조를 가집니다.
|
|
699
|
+
* 예시:
|
|
700
|
+
* {
|
|
701
|
+
* must: [ // 모든 조건이 참이어야 함
|
|
702
|
+
* { key: "field1", match: { value: "some_value" } },
|
|
703
|
+
* { key: "field2", range: { gte: 10, lt: 20 } }
|
|
704
|
+
* ],
|
|
705
|
+
* should: [ // 하나 이상의 조건이 참이어야 함
|
|
706
|
+
* { key: "field3", match: { value: "another_value" } },
|
|
707
|
+
* { key: "field4", match: { any: ["valueA", "valueB"] } }
|
|
708
|
+
* ],
|
|
709
|
+
* must_not: [ // 어떤 조건도 참이 아니어야 함
|
|
710
|
+
* { key: "field5", match: { value: "excluded_value" } }
|
|
711
|
+
* ]
|
|
712
|
+
* }
|
|
713
|
+
* @returns {Array<Object>} 필터링된 JSON 객체 배열입니다.
|
|
714
|
+
*/
|
|
715
|
+
static filter = (jsonArray, filter) => {
|
|
716
|
+
/**
|
|
717
|
+
* 단일 필터링 조건을 평가하는 헬퍼 함수입니다.
|
|
718
|
+
* @param {Object} item 현재 평가 중인 JSON 객체입니다.
|
|
719
|
+
* @param {Object} condition 평가할 단일 조건입니다. (예: { key: "field1", match: { value: "some_value" } })
|
|
720
|
+
* @returns {boolean} 조건이 참이면 true, 그렇지 않으면 false.
|
|
721
|
+
*/
|
|
722
|
+
const evaluateCondition = (item, condition) => {
|
|
723
|
+
const valueInItem = item[condition.key];
|
|
724
|
+
|
|
725
|
+
if (condition.match) {
|
|
726
|
+
const match = condition.match;
|
|
727
|
+
if (match.value !== undefined) {
|
|
728
|
+
return valueInItem === match.value;
|
|
729
|
+
}
|
|
730
|
+
if (match.any && Array.isArray(match.any)) {
|
|
731
|
+
return match.any.includes(valueInItem);
|
|
732
|
+
}
|
|
733
|
+
if (match.all && Array.isArray(match.all)) {
|
|
734
|
+
// item[condition.key]가 배열이라고 가정
|
|
735
|
+
if (!Array.isArray(valueInItem)) return false;
|
|
736
|
+
return match.all.every(val => valueInItem.includes(val));
|
|
737
|
+
}
|
|
738
|
+
if (match.text !== undefined) {
|
|
739
|
+
// 텍스트 매치는 부분 문자열 일치 또는 정규식 등으로 확장 가능
|
|
740
|
+
// 여기서는 단순 포함 여부로 구현
|
|
741
|
+
return typeof valueInItem === 'string' && valueInItem.includes(match.text);
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
if (condition.range) {
|
|
746
|
+
const range = condition.range;
|
|
747
|
+
if (typeof valueInItem !== 'number') return false; // 숫자가 아니면 범위 비교 불가
|
|
748
|
+
|
|
749
|
+
if (range.gte !== undefined && !(valueInItem >= range.gte)) return false;
|
|
750
|
+
if (range.gt !== undefined && !(valueInItem > range.gt)) return false;
|
|
751
|
+
if (range.lte !== undefined && !(valueInItem <= range.lte)) return false;
|
|
752
|
+
if (range.lt !== undefined && !(valueInItem < range.lt)) return false;
|
|
753
|
+
return true;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// 다른 필터 타입 (예: `geo_bounding_box`, `has_id` 등)은 필요에 따라 추가 구현
|
|
757
|
+
// 현재는 `match`와 `range`만 지원합니다.
|
|
758
|
+
|
|
759
|
+
return false; // 지원하지 않는 조건 타입
|
|
760
|
+
}
|
|
761
|
+
if (!jsonArray || !Array.isArray(jsonArray)) {
|
|
762
|
+
console.error("첫 번째 인수는 JSON 배열이어야 합니다.");
|
|
763
|
+
return [];
|
|
764
|
+
}
|
|
765
|
+
if (!filter || typeof filter !== 'object') {
|
|
766
|
+
// 필터 조건이 없거나 유효하지 않으면 원본 배열 반환
|
|
767
|
+
return jsonArray;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
return jsonArray.filter(item => {
|
|
771
|
+
// 'must' 조건 처리: 모든 'must' 조건이 참이어야 합니다.
|
|
772
|
+
if (filter.must && !filter.must.every(condition => evaluateCondition(item, condition))) {
|
|
773
|
+
return false;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
// 'should' 조건 처리: 하나 이상의 'should' 조건이 참이어야 합니다.
|
|
777
|
+
// 'should' 조건이 없으면 이 부분은 건너뜁니다.
|
|
778
|
+
if (filter.should && filter.should.length > 0 && !filter.should.some(condition => evaluateCondition(item, condition))) {
|
|
779
|
+
return false;
|
|
780
|
+
} else if (filter.should && filter.should.length === 0 && (filter.must || filter.must_not)) {
|
|
781
|
+
// 'should'가 비어있고 'must'나 'must_not'가 있으면 'should'는 필터링에 영향 없음.
|
|
782
|
+
// 하지만 'should'만 있고 비어있다면, 사실상 필터링이 안 되는 것과 같으므로 true 반환.
|
|
783
|
+
// 이 로직은 Qdrant의 'should'가 비어있을 때의 동작과 일치하도록 조정될 수 있습니다.
|
|
784
|
+
// 현재는 'should'가 비어있으면 필터링에 영향이 없도록 합니다.
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
// 'must_not' 조건 처리: 어떤 'must_not' 조건도 참이 아니어야 합니다.
|
|
789
|
+
if (filter.must_not && filter.must_not.some(condition => evaluateCondition(item, condition))) {
|
|
790
|
+
return false;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
return true;
|
|
794
|
+
});
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
|
|
798
|
+
|
|
799
|
+
|
|
800
|
+
|
|
693
801
|
static j = {
|
|
694
802
|
copyEvents: (source, target) => {
|
|
695
803
|
const events = getEventListeners(source);
|
package/package.json
CHANGED
package/src/ai/aiContainer.js
CHANGED
|
@@ -48,7 +48,7 @@ class aiContainer extends HTMLElement
|
|
|
48
48
|
</div>
|
|
49
49
|
<div class="menu">
|
|
50
50
|
<div class="collapse-icon"></div>
|
|
51
|
-
<div class="menu-icon menu-filter
|
|
51
|
+
<div class="menu-icon menu-filter active"></div>
|
|
52
52
|
<div class="menu-icon menu-general"></div>
|
|
53
53
|
<div class="menu-icon menu-setting"></div>
|
|
54
54
|
</div>
|
|
@@ -237,114 +237,11 @@ class aiContainer extends HTMLElement
|
|
|
237
237
|
//}
|
|
238
238
|
};
|
|
239
239
|
|
|
240
|
-
/**
|
|
241
|
-
* Qdrant 필터링 조건에 따라 JSON 배열을 필터링하는 함수입니다.
|
|
242
|
-
*
|
|
243
|
-
* @param {Array<Object>} jsonArray 필터링할 JSON 객체 배열입니다.
|
|
244
|
-
* @param {Object} filter 필터링 조건 객체입니다. Qdrant 필터와 유사한 구조를 가집니다.
|
|
245
|
-
* 예시:
|
|
246
|
-
* {
|
|
247
|
-
* must: [ // 모든 조건이 참이어야 함
|
|
248
|
-
* { key: "field1", match: { value: "some_value" } },
|
|
249
|
-
* { key: "field2", range: { gte: 10, lt: 20 } }
|
|
250
|
-
* ],
|
|
251
|
-
* should: [ // 하나 이상의 조건이 참이어야 함
|
|
252
|
-
* { key: "field3", match: { value: "another_value" } },
|
|
253
|
-
* { key: "field4", match: { any: ["valueA", "valueB"] } }
|
|
254
|
-
* ],
|
|
255
|
-
* must_not: [ // 어떤 조건도 참이 아니어야 함
|
|
256
|
-
* { key: "field5", match: { value: "excluded_value" } }
|
|
257
|
-
* ]
|
|
258
|
-
* }
|
|
259
|
-
* @returns {Array<Object>} 필터링된 JSON 객체 배열입니다.
|
|
260
|
-
*/
|
|
261
|
-
#filterJsonArray = (jsonArray, filter) => {
|
|
262
|
-
if (!jsonArray || !Array.isArray(jsonArray)) {
|
|
263
|
-
console.error("첫 번째 인수는 JSON 배열이어야 합니다.");
|
|
264
|
-
return [];
|
|
265
|
-
}
|
|
266
|
-
if (!filter || typeof filter !== 'object') {
|
|
267
|
-
// 필터 조건이 없거나 유효하지 않으면 원본 배열 반환
|
|
268
|
-
return jsonArray;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
return jsonArray.filter(item => {
|
|
272
|
-
// 'must' 조건 처리: 모든 'must' 조건이 참이어야 합니다.
|
|
273
|
-
if (filter.must && !filter.must.every(condition => this.#evaluateCondition(item, condition))) {
|
|
274
|
-
return false;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
// 'should' 조건 처리: 하나 이상의 'should' 조건이 참이어야 합니다.
|
|
278
|
-
// 'should' 조건이 없으면 이 부분은 건너뜁니다.
|
|
279
|
-
if (filter.should && filter.should.length > 0 && !filter.should.some(condition => this.#evaluateCondition(item, condition))) {
|
|
280
|
-
return false;
|
|
281
|
-
} else if (filter.should && filter.should.length === 0 && (filter.must || filter.must_not)) {
|
|
282
|
-
// 'should'가 비어있고 'must'나 'must_not'가 있으면 'should'는 필터링에 영향 없음.
|
|
283
|
-
// 하지만 'should'만 있고 비어있다면, 사실상 필터링이 안 되는 것과 같으므로 true 반환.
|
|
284
|
-
// 이 로직은 Qdrant의 'should'가 비어있을 때의 동작과 일치하도록 조정될 수 있습니다.
|
|
285
|
-
// 현재는 'should'가 비어있으면 필터링에 영향이 없도록 합니다.
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
// 'must_not' 조건 처리: 어떤 'must_not' 조건도 참이 아니어야 합니다.
|
|
290
|
-
if (filter.must_not && filter.must_not.some(condition => this.#evaluateCondition(item, condition))) {
|
|
291
|
-
return false;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
return true;
|
|
295
|
-
});
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
/**
|
|
299
|
-
* 단일 필터링 조건을 평가하는 헬퍼 함수입니다.
|
|
300
|
-
* @param {Object} item 현재 평가 중인 JSON 객체입니다.
|
|
301
|
-
* @param {Object} condition 평가할 단일 조건입니다. (예: { key: "field1", match: { value: "some_value" } })
|
|
302
|
-
* @returns {boolean} 조건이 참이면 true, 그렇지 않으면 false.
|
|
303
|
-
*/
|
|
304
|
-
#evaluateCondition = (item, condition) => {
|
|
305
|
-
const valueInItem = item[condition.key];
|
|
306
|
-
|
|
307
|
-
if (condition.match) {
|
|
308
|
-
const match = condition.match;
|
|
309
|
-
if (match.value !== undefined) {
|
|
310
|
-
return valueInItem === match.value;
|
|
311
|
-
}
|
|
312
|
-
if (match.any && Array.isArray(match.any)) {
|
|
313
|
-
return match.any.includes(valueInItem);
|
|
314
|
-
}
|
|
315
|
-
if (match.all && Array.isArray(match.all)) {
|
|
316
|
-
// item[condition.key]가 배열이라고 가정
|
|
317
|
-
if (!Array.isArray(valueInItem)) return false;
|
|
318
|
-
return match.all.every(val => valueInItem.includes(val));
|
|
319
|
-
}
|
|
320
|
-
if (match.text !== undefined) {
|
|
321
|
-
// 텍스트 매치는 부분 문자열 일치 또는 정규식 등으로 확장 가능
|
|
322
|
-
// 여기서는 단순 포함 여부로 구현
|
|
323
|
-
return typeof valueInItem === 'string' && valueInItem.includes(match.text);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
if (condition.range) {
|
|
328
|
-
const range = condition.range;
|
|
329
|
-
if (typeof valueInItem !== 'number') return false; // 숫자가 아니면 범위 비교 불가
|
|
330
|
-
|
|
331
|
-
if (range.gte !== undefined && !(valueInItem >= range.gte)) return false;
|
|
332
|
-
if (range.gt !== undefined && !(valueInItem > range.gt)) return false;
|
|
333
|
-
if (range.lte !== undefined && !(valueInItem <= range.lte)) return false;
|
|
334
|
-
if (range.lt !== undefined && !(valueInItem < range.lt)) return false;
|
|
335
|
-
return true;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// 다른 필터 타입 (예: `geo_bounding_box`, `has_id` 등)은 필요에 따라 추가 구현
|
|
339
|
-
// 현재는 `match`와 `range`만 지원합니다.
|
|
340
|
-
|
|
341
|
-
return false; // 지원하지 않는 조건 타입
|
|
342
|
-
}
|
|
343
240
|
|
|
344
241
|
|
|
345
242
|
#q1 = async () => {
|
|
346
243
|
const filter = await this.#generateQdrantFilter();
|
|
347
|
-
const searchResults =
|
|
244
|
+
const searchResults = ninegrid.filter(this.#getData(), filter);
|
|
348
245
|
|
|
349
246
|
await this.#answer(searchResults);
|
|
350
247
|
};
|
|
@@ -361,16 +258,17 @@ class aiContainer extends HTMLElement
|
|
|
361
258
|
const columnInfo = this.#getColumnInfo();
|
|
362
259
|
const uniqueKey = this.#getUniqueKey();
|
|
363
260
|
|
|
364
|
-
console.log(
|
|
261
|
+
console.log(searchResults);
|
|
365
262
|
|
|
366
263
|
if (!searchResults || searchResults.length == 0) {
|
|
367
264
|
elAiChat.add("ai", "관련된 정보가 없습니다.");
|
|
368
265
|
}
|
|
369
266
|
else if (searchResults.length > 100) {
|
|
370
|
-
elAiChat.add("ai", `${searchResults.length}건의 정보를 찾았습니다.`, columnInfo, searchResults.map(item => item.payload), uniqueKey);
|
|
267
|
+
//elAiChat.add("ai", `${searchResults.length}건의 정보를 찾았습니다.`, columnInfo, searchResults.map(item => item.payload), uniqueKey);
|
|
268
|
+
elAiChat.add("ai", `${searchResults.length}건의 정보를 찾았습니다.`, columnInfo, searchResults, uniqueKey);
|
|
371
269
|
}
|
|
372
270
|
else {
|
|
373
|
-
let arr = searchResults.map(item => item.payload);
|
|
271
|
+
//let arr = searchResults.map(item => item.payload);
|
|
374
272
|
let contextText = `당신은 주어진 정보를 참고하여 답변하는 AI 입니다. 주어진 '정보'를 바탕으로 데이타를 분석해줘. 데이타는 "context" 항목에 있어. 제공될 데이터는 CSV 형식이며, 첫 번째 줄은 컬럼명입니다. 이전에 너가 찾아준 데이타를 다시 보내는거니깐 첫 줄에는 "${arr.length}건을 찾았습니다." 라고 답변을 달아줘.\n\ncontext: `;
|
|
375
273
|
|
|
376
274
|
let contextText1 = `당신은 주어진 데이터를 분석하고 핵심 인사이트를 도출하는 전문 데이터 분석가입니다.
|
|
@@ -398,7 +296,9 @@ class aiContainer extends HTMLElement
|
|
|
398
296
|
});
|
|
399
297
|
contextText += "\n";
|
|
400
298
|
|
|
401
|
-
for (const o of
|
|
299
|
+
for (const o of searchResults) {
|
|
300
|
+
|
|
301
|
+
console.log(o);
|
|
402
302
|
columnInfo.forEach(info => {
|
|
403
303
|
contextText += `${o[info.name]}\t`;
|
|
404
304
|
});
|
|
@@ -476,7 +376,7 @@ class aiContainer extends HTMLElement
|
|
|
476
376
|
await this.#q2();
|
|
477
377
|
}
|
|
478
378
|
} catch (error) {
|
|
479
|
-
|
|
379
|
+
console.error(error);
|
|
480
380
|
elAiChat.add("ai", error);
|
|
481
381
|
}
|
|
482
382
|
|
package/src/utils/ninegrid.js
CHANGED
|
@@ -690,6 +690,114 @@ export class ninegrid {
|
|
|
690
690
|
return nxAlertPopup.alert(message, title, options);
|
|
691
691
|
}
|
|
692
692
|
|
|
693
|
+
|
|
694
|
+
/**
|
|
695
|
+
* Qdrant 필터링 조건에 따라 JSON 배열을 필터링하는 함수입니다.
|
|
696
|
+
*
|
|
697
|
+
* @param {Array<Object>} jsonArray 필터링할 JSON 객체 배열입니다.
|
|
698
|
+
* @param {Object} filter 필터링 조건 객체입니다. Qdrant 필터와 유사한 구조를 가집니다.
|
|
699
|
+
* 예시:
|
|
700
|
+
* {
|
|
701
|
+
* must: [ // 모든 조건이 참이어야 함
|
|
702
|
+
* { key: "field1", match: { value: "some_value" } },
|
|
703
|
+
* { key: "field2", range: { gte: 10, lt: 20 } }
|
|
704
|
+
* ],
|
|
705
|
+
* should: [ // 하나 이상의 조건이 참이어야 함
|
|
706
|
+
* { key: "field3", match: { value: "another_value" } },
|
|
707
|
+
* { key: "field4", match: { any: ["valueA", "valueB"] } }
|
|
708
|
+
* ],
|
|
709
|
+
* must_not: [ // 어떤 조건도 참이 아니어야 함
|
|
710
|
+
* { key: "field5", match: { value: "excluded_value" } }
|
|
711
|
+
* ]
|
|
712
|
+
* }
|
|
713
|
+
* @returns {Array<Object>} 필터링된 JSON 객체 배열입니다.
|
|
714
|
+
*/
|
|
715
|
+
static filter = (jsonArray, filter) => {
|
|
716
|
+
/**
|
|
717
|
+
* 단일 필터링 조건을 평가하는 헬퍼 함수입니다.
|
|
718
|
+
* @param {Object} item 현재 평가 중인 JSON 객체입니다.
|
|
719
|
+
* @param {Object} condition 평가할 단일 조건입니다. (예: { key: "field1", match: { value: "some_value" } })
|
|
720
|
+
* @returns {boolean} 조건이 참이면 true, 그렇지 않으면 false.
|
|
721
|
+
*/
|
|
722
|
+
const evaluateCondition = (item, condition) => {
|
|
723
|
+
const valueInItem = item[condition.key];
|
|
724
|
+
|
|
725
|
+
if (condition.match) {
|
|
726
|
+
const match = condition.match;
|
|
727
|
+
if (match.value !== undefined) {
|
|
728
|
+
return valueInItem === match.value;
|
|
729
|
+
}
|
|
730
|
+
if (match.any && Array.isArray(match.any)) {
|
|
731
|
+
return match.any.includes(valueInItem);
|
|
732
|
+
}
|
|
733
|
+
if (match.all && Array.isArray(match.all)) {
|
|
734
|
+
// item[condition.key]가 배열이라고 가정
|
|
735
|
+
if (!Array.isArray(valueInItem)) return false;
|
|
736
|
+
return match.all.every(val => valueInItem.includes(val));
|
|
737
|
+
}
|
|
738
|
+
if (match.text !== undefined) {
|
|
739
|
+
// 텍스트 매치는 부분 문자열 일치 또는 정규식 등으로 확장 가능
|
|
740
|
+
// 여기서는 단순 포함 여부로 구현
|
|
741
|
+
return typeof valueInItem === 'string' && valueInItem.includes(match.text);
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
if (condition.range) {
|
|
746
|
+
const range = condition.range;
|
|
747
|
+
if (typeof valueInItem !== 'number') return false; // 숫자가 아니면 범위 비교 불가
|
|
748
|
+
|
|
749
|
+
if (range.gte !== undefined && !(valueInItem >= range.gte)) return false;
|
|
750
|
+
if (range.gt !== undefined && !(valueInItem > range.gt)) return false;
|
|
751
|
+
if (range.lte !== undefined && !(valueInItem <= range.lte)) return false;
|
|
752
|
+
if (range.lt !== undefined && !(valueInItem < range.lt)) return false;
|
|
753
|
+
return true;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// 다른 필터 타입 (예: `geo_bounding_box`, `has_id` 등)은 필요에 따라 추가 구현
|
|
757
|
+
// 현재는 `match`와 `range`만 지원합니다.
|
|
758
|
+
|
|
759
|
+
return false; // 지원하지 않는 조건 타입
|
|
760
|
+
}
|
|
761
|
+
if (!jsonArray || !Array.isArray(jsonArray)) {
|
|
762
|
+
console.error("첫 번째 인수는 JSON 배열이어야 합니다.");
|
|
763
|
+
return [];
|
|
764
|
+
}
|
|
765
|
+
if (!filter || typeof filter !== 'object') {
|
|
766
|
+
// 필터 조건이 없거나 유효하지 않으면 원본 배열 반환
|
|
767
|
+
return jsonArray;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
return jsonArray.filter(item => {
|
|
771
|
+
// 'must' 조건 처리: 모든 'must' 조건이 참이어야 합니다.
|
|
772
|
+
if (filter.must && !filter.must.every(condition => evaluateCondition(item, condition))) {
|
|
773
|
+
return false;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
// 'should' 조건 처리: 하나 이상의 'should' 조건이 참이어야 합니다.
|
|
777
|
+
// 'should' 조건이 없으면 이 부분은 건너뜁니다.
|
|
778
|
+
if (filter.should && filter.should.length > 0 && !filter.should.some(condition => evaluateCondition(item, condition))) {
|
|
779
|
+
return false;
|
|
780
|
+
} else if (filter.should && filter.should.length === 0 && (filter.must || filter.must_not)) {
|
|
781
|
+
// 'should'가 비어있고 'must'나 'must_not'가 있으면 'should'는 필터링에 영향 없음.
|
|
782
|
+
// 하지만 'should'만 있고 비어있다면, 사실상 필터링이 안 되는 것과 같으므로 true 반환.
|
|
783
|
+
// 이 로직은 Qdrant의 'should'가 비어있을 때의 동작과 일치하도록 조정될 수 있습니다.
|
|
784
|
+
// 현재는 'should'가 비어있으면 필터링에 영향이 없도록 합니다.
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
// 'must_not' 조건 처리: 어떤 'must_not' 조건도 참이 아니어야 합니다.
|
|
789
|
+
if (filter.must_not && filter.must_not.some(condition => evaluateCondition(item, condition))) {
|
|
790
|
+
return false;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
return true;
|
|
794
|
+
});
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
|
|
798
|
+
|
|
799
|
+
|
|
800
|
+
|
|
693
801
|
static j = {
|
|
694
802
|
copyEvents: (source, target) => {
|
|
695
803
|
const events = getEventListeners(source);
|