ninegrid2 6.530.0 → 6.532.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 +121 -6
- package/dist/bundle.cjs.js +116 -6
- package/dist/bundle.esm.js +116 -6
- package/package.json +1 -1
- package/src/ai/aiContainer.js +121 -6
package/dist/ai/aiContainer.js
CHANGED
|
@@ -48,9 +48,8 @@ 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"></div>
|
|
52
|
-
<div class="menu-icon menu-general
|
|
53
|
-
<div class="menu-icon menu-db"></div>
|
|
51
|
+
<div class="menu-icon menu-filter" active></div>
|
|
52
|
+
<div class="menu-icon menu-general"></div>
|
|
54
53
|
<div class="menu-icon menu-setting"></div>
|
|
55
54
|
</div>
|
|
56
55
|
</div>
|
|
@@ -116,6 +115,12 @@ class aiContainer extends HTMLElement
|
|
|
116
115
|
}
|
|
117
116
|
};
|
|
118
117
|
|
|
118
|
+
#getData = () => {
|
|
119
|
+
if (this.#target.tagName === "NINE-GRID") {
|
|
120
|
+
return this.#target.data.get();
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
119
124
|
|
|
120
125
|
#generateQdrantFilter = async () => {
|
|
121
126
|
|
|
@@ -230,17 +235,128 @@ class aiContainer extends HTMLElement
|
|
|
230
235
|
// console.error("Error during Qdrant search:", error);
|
|
231
236
|
return [];
|
|
232
237
|
//}
|
|
238
|
+
};
|
|
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
|
+
});
|
|
233
296
|
}
|
|
234
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
|
+
|
|
344
|
+
|
|
235
345
|
#q1 = async () => {
|
|
236
|
-
|
|
237
|
-
|
|
346
|
+
const filter = await this.#generateQdrantFilter();
|
|
347
|
+
const searchResults = await this.#filterJsonArray(this.#getData(), filter);
|
|
348
|
+
|
|
349
|
+
await this.#answer(searchResults);
|
|
238
350
|
};
|
|
239
351
|
|
|
240
352
|
#q2 = async () => {
|
|
241
353
|
const filter = await this.#generateQdrantFilter();
|
|
242
354
|
const searchResults = await this.#searchWithQdrantFilter(filter);
|
|
243
355
|
|
|
356
|
+
await this.#answer(searchResults);
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
#answer = async (searchResults) => {
|
|
244
360
|
const elAiChat = this.shadowRoot.querySelector("nx-ai-chat");
|
|
245
361
|
const columnInfo = this.#getColumnInfo();
|
|
246
362
|
const uniqueKey = this.#getUniqueKey();
|
|
@@ -307,7 +423,6 @@ class aiContainer extends HTMLElement
|
|
|
307
423
|
}
|
|
308
424
|
};
|
|
309
425
|
|
|
310
|
-
|
|
311
426
|
#init = (info) => {
|
|
312
427
|
|
|
313
428
|
//this.#elChat = this.shadowRoot.querySelector("nx-ai-chat");
|
package/dist/bundle.cjs.js
CHANGED
|
@@ -54142,9 +54142,8 @@ class aiContainer extends HTMLElement
|
|
|
54142
54142
|
</div>
|
|
54143
54143
|
<div class="menu">
|
|
54144
54144
|
<div class="collapse-icon"></div>
|
|
54145
|
-
<div class="menu-icon menu-filter"></div>
|
|
54146
|
-
<div class="menu-icon menu-general
|
|
54147
|
-
<div class="menu-icon menu-db"></div>
|
|
54145
|
+
<div class="menu-icon menu-filter" active></div>
|
|
54146
|
+
<div class="menu-icon menu-general"></div>
|
|
54148
54147
|
<div class="menu-icon menu-setting"></div>
|
|
54149
54148
|
</div>
|
|
54150
54149
|
</div>
|
|
@@ -54210,6 +54209,12 @@ class aiContainer extends HTMLElement
|
|
|
54210
54209
|
}
|
|
54211
54210
|
};
|
|
54212
54211
|
|
|
54212
|
+
#getData = () => {
|
|
54213
|
+
if (this.#target.tagName === "NINE-GRID") {
|
|
54214
|
+
return this.#target.data.get();
|
|
54215
|
+
}
|
|
54216
|
+
};
|
|
54217
|
+
|
|
54213
54218
|
|
|
54214
54219
|
#generateQdrantFilter = async () => {
|
|
54215
54220
|
|
|
@@ -54320,17 +54325,123 @@ class aiContainer extends HTMLElement
|
|
|
54320
54325
|
|
|
54321
54326
|
return await this.#qdrantClient.search(collectionName, searchParams);
|
|
54322
54327
|
//}
|
|
54328
|
+
};
|
|
54329
|
+
|
|
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
|
+
});
|
|
54323
54381
|
}
|
|
54324
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
|
+
|
|
54429
|
+
|
|
54325
54430
|
#q1 = async () => {
|
|
54326
|
-
|
|
54327
|
-
|
|
54431
|
+
const filter = await this.#generateQdrantFilter();
|
|
54432
|
+
const searchResults = await this.#filterJsonArray(this.#getData(), filter);
|
|
54433
|
+
|
|
54434
|
+
await this.#answer(searchResults);
|
|
54328
54435
|
};
|
|
54329
54436
|
|
|
54330
54437
|
#q2 = async () => {
|
|
54331
54438
|
const filter = await this.#generateQdrantFilter();
|
|
54332
54439
|
const searchResults = await this.#searchWithQdrantFilter(filter);
|
|
54333
54440
|
|
|
54441
|
+
await this.#answer(searchResults);
|
|
54442
|
+
};
|
|
54443
|
+
|
|
54444
|
+
#answer = async (searchResults) => {
|
|
54334
54445
|
const elAiChat = this.shadowRoot.querySelector("nx-ai-chat");
|
|
54335
54446
|
const columnInfo = this.#getColumnInfo();
|
|
54336
54447
|
const uniqueKey = this.#getUniqueKey();
|
|
@@ -54377,7 +54488,6 @@ class aiContainer extends HTMLElement
|
|
|
54377
54488
|
}
|
|
54378
54489
|
};
|
|
54379
54490
|
|
|
54380
|
-
|
|
54381
54491
|
#init = (info) => {
|
|
54382
54492
|
|
|
54383
54493
|
//this.#elChat = this.shadowRoot.querySelector("nx-ai-chat");
|
package/dist/bundle.esm.js
CHANGED
|
@@ -54140,9 +54140,8 @@ class aiContainer extends HTMLElement
|
|
|
54140
54140
|
</div>
|
|
54141
54141
|
<div class="menu">
|
|
54142
54142
|
<div class="collapse-icon"></div>
|
|
54143
|
-
<div class="menu-icon menu-filter"></div>
|
|
54144
|
-
<div class="menu-icon menu-general
|
|
54145
|
-
<div class="menu-icon menu-db"></div>
|
|
54143
|
+
<div class="menu-icon menu-filter" active></div>
|
|
54144
|
+
<div class="menu-icon menu-general"></div>
|
|
54146
54145
|
<div class="menu-icon menu-setting"></div>
|
|
54147
54146
|
</div>
|
|
54148
54147
|
</div>
|
|
@@ -54208,6 +54207,12 @@ class aiContainer extends HTMLElement
|
|
|
54208
54207
|
}
|
|
54209
54208
|
};
|
|
54210
54209
|
|
|
54210
|
+
#getData = () => {
|
|
54211
|
+
if (this.#target.tagName === "NINE-GRID") {
|
|
54212
|
+
return this.#target.data.get();
|
|
54213
|
+
}
|
|
54214
|
+
};
|
|
54215
|
+
|
|
54211
54216
|
|
|
54212
54217
|
#generateQdrantFilter = async () => {
|
|
54213
54218
|
|
|
@@ -54318,17 +54323,123 @@ class aiContainer extends HTMLElement
|
|
|
54318
54323
|
|
|
54319
54324
|
return await this.#qdrantClient.search(collectionName, searchParams);
|
|
54320
54325
|
//}
|
|
54326
|
+
};
|
|
54327
|
+
|
|
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
|
+
});
|
|
54321
54379
|
}
|
|
54322
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
|
+
|
|
54427
|
+
|
|
54323
54428
|
#q1 = async () => {
|
|
54324
|
-
|
|
54325
|
-
|
|
54429
|
+
const filter = await this.#generateQdrantFilter();
|
|
54430
|
+
const searchResults = await this.#filterJsonArray(this.#getData(), filter);
|
|
54431
|
+
|
|
54432
|
+
await this.#answer(searchResults);
|
|
54326
54433
|
};
|
|
54327
54434
|
|
|
54328
54435
|
#q2 = async () => {
|
|
54329
54436
|
const filter = await this.#generateQdrantFilter();
|
|
54330
54437
|
const searchResults = await this.#searchWithQdrantFilter(filter);
|
|
54331
54438
|
|
|
54439
|
+
await this.#answer(searchResults);
|
|
54440
|
+
};
|
|
54441
|
+
|
|
54442
|
+
#answer = async (searchResults) => {
|
|
54332
54443
|
const elAiChat = this.shadowRoot.querySelector("nx-ai-chat");
|
|
54333
54444
|
const columnInfo = this.#getColumnInfo();
|
|
54334
54445
|
const uniqueKey = this.#getUniqueKey();
|
|
@@ -54375,7 +54486,6 @@ class aiContainer extends HTMLElement
|
|
|
54375
54486
|
}
|
|
54376
54487
|
};
|
|
54377
54488
|
|
|
54378
|
-
|
|
54379
54489
|
#init = (info) => {
|
|
54380
54490
|
|
|
54381
54491
|
//this.#elChat = this.shadowRoot.querySelector("nx-ai-chat");
|
package/package.json
CHANGED
package/src/ai/aiContainer.js
CHANGED
|
@@ -48,9 +48,8 @@ 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"></div>
|
|
52
|
-
<div class="menu-icon menu-general
|
|
53
|
-
<div class="menu-icon menu-db"></div>
|
|
51
|
+
<div class="menu-icon menu-filter" active></div>
|
|
52
|
+
<div class="menu-icon menu-general"></div>
|
|
54
53
|
<div class="menu-icon menu-setting"></div>
|
|
55
54
|
</div>
|
|
56
55
|
</div>
|
|
@@ -116,6 +115,12 @@ class aiContainer extends HTMLElement
|
|
|
116
115
|
}
|
|
117
116
|
};
|
|
118
117
|
|
|
118
|
+
#getData = () => {
|
|
119
|
+
if (this.#target.tagName === "NINE-GRID") {
|
|
120
|
+
return this.#target.data.get();
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
119
124
|
|
|
120
125
|
#generateQdrantFilter = async () => {
|
|
121
126
|
|
|
@@ -230,17 +235,128 @@ class aiContainer extends HTMLElement
|
|
|
230
235
|
// console.error("Error during Qdrant search:", error);
|
|
231
236
|
return [];
|
|
232
237
|
//}
|
|
238
|
+
};
|
|
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
|
+
});
|
|
233
296
|
}
|
|
234
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
|
+
|
|
344
|
+
|
|
235
345
|
#q1 = async () => {
|
|
236
|
-
|
|
237
|
-
|
|
346
|
+
const filter = await this.#generateQdrantFilter();
|
|
347
|
+
const searchResults = await this.#filterJsonArray(this.#getData(), filter);
|
|
348
|
+
|
|
349
|
+
await this.#answer(searchResults);
|
|
238
350
|
};
|
|
239
351
|
|
|
240
352
|
#q2 = async () => {
|
|
241
353
|
const filter = await this.#generateQdrantFilter();
|
|
242
354
|
const searchResults = await this.#searchWithQdrantFilter(filter);
|
|
243
355
|
|
|
356
|
+
await this.#answer(searchResults);
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
#answer = async (searchResults) => {
|
|
244
360
|
const elAiChat = this.shadowRoot.querySelector("nx-ai-chat");
|
|
245
361
|
const columnInfo = this.#getColumnInfo();
|
|
246
362
|
const uniqueKey = this.#getUniqueKey();
|
|
@@ -307,7 +423,6 @@ class aiContainer extends HTMLElement
|
|
|
307
423
|
}
|
|
308
424
|
};
|
|
309
425
|
|
|
310
|
-
|
|
311
426
|
#init = (info) => {
|
|
312
427
|
|
|
313
428
|
//this.#elChat = this.shadowRoot.querySelector("nx-ai-chat");
|