Skip to content

Commit 199a335

Browse files
authoredAug 12, 2024
Merge pull request #186 from iceljc/features/refine-knowledge-window
Features/refine knowledge window
2 parents e7a82b1 + ddc9bdd commit 199a335

File tree

18 files changed

+729
-142
lines changed

18 files changed

+729
-142
lines changed
 

‎src/lib/common/Loader.svelte

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
<script>
22
import { Circle } from 'svelte-loading-spinners';
3+
4+
export let disableDefaultStyles = false;
5+
export let containerClasses = '';
36
export let size = 100;
47
</script>
58

6-
<div class="loader">
9+
<div class="{disableDefaultStyles ? '' : 'loader'} {containerClasses}">
710
<Circle {size} color="var(--bs-primary)" unit="px" duration="1s" />
811
</div>

‎src/lib/helpers/constants.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,6 @@ export const FILE_EDITORS = [
2424
];
2525

2626
export const LERNER_ID = "01acc3e5-0af7-49e6-ad7a-a760bd12dc40";
27-
export const TRAINING_MODE = "training";
27+
export const TRAINING_MODE = "training";
28+
29+
export const KNOWLEDGE_COLLECTION = "BotSharp";

‎src/lib/helpers/http.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ axios.interceptors.response.use(
5656
function skipLoader(config) {
5757
const postRegexes = [
5858
new RegExp('http(s*)://(.*?)/conversation/(.*?)/(.*?)', 'g'),
59-
new RegExp('http(s*)://(.*?)/agent', 'g')
59+
new RegExp('http(s*)://(.*?)/agent', 'g'),
60+
new RegExp('http(s*)://(.*?)/knowledge/(.*?)/data', 'g'),
61+
new RegExp('http(s*)://(.*?)/knowledge/(.*?)/search', 'g')
6062
];
6163

6264
const getRegexes = [

‎src/lib/helpers/types/types.js

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,13 @@
216216

217217

218218
// File models
219+
/**
220+
* @typedef {Object} FileModel
221+
* @property {string} file_name - The file name.
222+
* @property {string} file_data - The file data.
223+
* @property {string} file_url - The file url.
224+
*/
225+
219226
/**
220227
* @typedef {Object} TextFileModel
221228
* @property {string} file_name - The file name.
@@ -453,13 +460,46 @@ IRichContent.prototype.quick_replies;
453460
* @property {string?} [payload] - The payload message.
454461
*/
455462

463+
// Knowledgebase
456464
/**
457-
* @typedef {Object} FileModel
458-
* @property {string} file_name - The plugin full name.
459-
* @property {string} file_data - The plugin name.
460-
* @property {string} file_url - Row count.
465+
* @typedef {Object} SearchKnowledgeRequest
466+
* @property {string} text - The text.
467+
* @property {string} [fields] - Data fields.
468+
* @property {number} [limit] - Data limit.
469+
* @property {number} [confidence] - Confidence.
470+
* @property {boolean} [with_vector] - Include vector or not.
461471
*/
462472

473+
/**
474+
* @typedef {Object} KnowledgeFilter
475+
* @property {string | null} [start_id] - The start id.
476+
* @property {number} size - Page size.
477+
* @property {boolean} [with_vector] - Include vector or not.
478+
*/
479+
480+
/**
481+
* @typedef {Object} KnowledgeRetrivalViewModel
482+
* @property {any} data - The knowledge data.
483+
* @property {number} score - The knowledge score.
484+
* @property {number[]} [vector] - The knowledge vector.
485+
*/
486+
487+
/**
488+
* @typedef {Object} KnowledgeCollectionDataViewModel
489+
* @property {string} id - The knowledge data id.
490+
* @property {string} question - The question.
491+
* @property {string} answer - The answer.
492+
* @property {number[]} [vector] - The knowledge vector.
493+
*/
494+
495+
/**
496+
* @typedef {Object} KnowledgeCollectionDataResult
497+
* @property {number} count - The total data count.
498+
* @property {KnowledgeCollectionDataViewModel[]} items - The data items.
499+
* @property {string} [next_id] - The next id.
500+
*/
501+
502+
463503
/**
464504
* Invoked when a new conersation is created.
465505
* This callback type is called `requestCallback` and is displayed as a global symbol.

‎src/lib/scss/app.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ File: Main Css File
8989
@import "custom/pages/jobs";
9090
@import "custom/pages/conversation";
9191
@import "custom/pages/agent";
92+
@import "custom/pages/knowledgebase";
9293

9394
// Common
9495
@import "custom/common/animation";
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
.knowledge-demo-btn {
2+
display: flex;
3+
justify-content: flex-start;
4+
gap: 10px;
5+
6+
.btn-content {
7+
display: flex;
8+
justify-content: center;
9+
gap: 3px;
10+
flex-wrap: wrap;
11+
}
12+
13+
.btn-icon {
14+
display: flex;
15+
flex-direction: column;
16+
justify-content: center;
17+
}
18+
19+
.demo-tip {
20+
font-size: 18px;
21+
}
22+
}
23+
24+
.knowledge-search-container {
25+
.search-textarea {
26+
border-radius: 5px;
27+
border-color: var(--#{$prefix}light) !important;
28+
background-color: var(--#{$prefix}light) !important;
29+
scrollbar-width: thin;
30+
}
31+
32+
.text-count {
33+
margin-top: 2px;
34+
font-size: 10px;
35+
}
36+
37+
.knowledge-search-result-container {
38+
.list-open {
39+
list-style-type: disclosure-open;
40+
}
41+
42+
.list-closed {
43+
list-style-type: disclosure-closed;
44+
}
45+
46+
.result-item {
47+
margin: 5px 0px;
48+
font-size: 15px;
49+
50+
.result-key {
51+
font-size: 17px;
52+
}
53+
54+
.result-content {
55+
word-break: normal;
56+
}
57+
58+
.result-score {
59+
margin-top: 5px;
60+
}
61+
}
62+
}
63+
}
64+
65+
.knowledge-table {
66+
overflow: hidden;
67+
68+
.knowledge-text {
69+
width: 40%;
70+
max-width: 50px;
71+
72+
.ellipsis {
73+
white-space: nowrap;
74+
overflow: hidden;
75+
text-overflow: ellipsis;
76+
}
77+
}
78+
79+
.knowledge-op {
80+
width: 20%;
81+
82+
.knowledge-op-list {
83+
justify-content: center;
84+
}
85+
}
86+
87+
.knowledge-detail {
88+
padding: 2px 5px;
89+
border-radius: 3px;
90+
border-color: var(--#{$prefix}light) !important;
91+
background-color: var(--#{$prefix}light) !important;
92+
93+
ul {
94+
margin: 15px 0px;
95+
list-style-type: square;
96+
97+
li {
98+
margin: 5px 0px;
99+
}
100+
}
101+
102+
.wrappable {
103+
white-space: wrap !important;
104+
}
105+
}
106+
}
107+
108+
.knowledge-loader {
109+
display: flex;
110+
justify-content: center;
111+
}

‎src/lib/services/api-endpoints.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@ export const endpoints = {
5959
loggingStateLogUrl: `${host}/logger/conversation/{conversationId}/state-log`,
6060

6161
// knowledge base
62-
knowledgeBaseUploadUrl: `${host}/knowledge-base/upload`,
62+
knowledgeBaseUploadUrl: `${host}/knowledge/{collection}/upload`,
63+
knowledgeBaseDataListUrl: `${host}/knowledge/{collection}/data`,
64+
knowledgeBaseSearchUrl: `${host}/knowledge/{collection}/search`,
65+
knowledgeBaseDeleteDataUrl: `${host}/knowledge/{collection}/data/{id}`,
6366

6467
// chathub
6568
chatHubUrl: `${host}/chatHub`,

‎src/lib/services/knowledge-base-service.js

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,81 @@
1+
import { KNOWLEDGE_COLLECTION } from '$lib/helpers/constants.js';
2+
import { replaceUrl } from '$lib/helpers/http.js';
13
import { endpoints } from './api-endpoints.js';
24
import axios from 'axios';
35

6+
/**
7+
* @param {import('$types').SearchKnowledgeRequest} request
8+
* @param {string | null} [collection]
9+
* @returns {Promise<import('$types').KnowledgeRetrivalViewModel[]>}
10+
*/
11+
export async function searchKnowledge(request, collection = null) {
12+
const url = replaceUrl(endpoints.knowledgeBaseSearchUrl, {
13+
collection: collection || KNOWLEDGE_COLLECTION
14+
});
15+
16+
const body = {
17+
...request,
18+
fields: request.fields || ["text", "answer"]
19+
};
20+
const response = await axios.post(url, { ...body });
21+
return response.data;
22+
}
23+
24+
/**
25+
* @param {import('$types').KnowledgeFilter} filter
26+
* @param {string | null} [collection]
27+
* @returns {Promise<import('$types').KnowledgeCollectionDataResult>}
28+
*/
29+
export async function getKnowledgeData(filter, collection = null) {
30+
const url = replaceUrl(endpoints.knowledgeBaseDataListUrl, {
31+
collection: collection || KNOWLEDGE_COLLECTION
32+
});
33+
34+
const response = await axios.post(url, { ...filter });
35+
return response.data;
36+
}
37+
38+
39+
/**
40+
* @param {string} id
41+
* @param {string | null} [collection]
42+
* @returns {Promise<boolean>}
43+
*/
44+
export async function deleteKnowledgeData(id, collection = null) {
45+
const url = replaceUrl(endpoints.knowledgeBaseDeleteDataUrl, {
46+
collection: collection || KNOWLEDGE_COLLECTION,
47+
id: id
48+
});
49+
50+
const response = await axios.delete(url);
51+
return response.data;
52+
}
53+
54+
455
/**
556
* Upload document to knowledge base.
657
* @param {File} file
58+
* @param {string | null} [collection]
59+
* @param {number | null} [startPageNum]
60+
* @param {number | null} [endPageNum]
761
*/
8-
export async function uploadDocument(file) {
9-
let url = endpoints.knowledgeBaseUploadUrl;
62+
export async function uploadKnowledge(file, collection = null, startPageNum = null, endPageNum = null) {
63+
const url = replaceUrl(endpoints.knowledgeBaseUploadUrl, {
64+
collection: collection || KNOWLEDGE_COLLECTION
65+
});
1066

1167
const formData = new FormData();
1268
formData.append("file", file);
1369

14-
let config = {
70+
if (startPageNum) {
71+
formData.append("startPageNum", startPageNum.toString());
72+
}
73+
74+
if (endPageNum) {
75+
formData.append("endPageNum", endPageNum.toString());
76+
}
77+
78+
const config = {
1579
headers: {
1680
"Content-Type": "multipart/form-data"
1781
}

‎src/routes/page/conversation/+page.svelte

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import StateModal from '$lib/common/StateModal.svelte';
2222
import { conversationSearchOptionStore } from '$lib/helpers/store';
2323
import { onMount } from 'svelte';
24-
import Link from 'svelte-link';
2524
import { getAgents } from '$lib/services/agent-service';
2625
import { getConversations, deleteConversation } from '$lib/services/conversation-service.js';
2726
import { utcToLocal } from '$lib/helpers/datetime';
@@ -347,7 +346,12 @@
347346
<div class="d-flex align-items-center">
348347
<h5 class="mb-0 card-title flex-grow-1">{$_('Conversation List')}</h5>
349348
<div class="flex-shrink-0">
350-
<Link class="btn btn-light" on:click={(e) => searchConversations(e)}><i class="mdi mdi-magnify" /></Link>
349+
<Button
350+
class="btn btn-light"
351+
on:click={(e) => searchConversations(e)}
352+
>
353+
<i class="mdi mdi-magnify" />
354+
</Button>
351355
<Dropdown class="dropdown d-inline-block">
352356
<DropdownToggle type="menu" class="btn" id="dropdownMenuButton1">
353357
<i class="mdi mdi-dots-vertical" />
@@ -442,17 +446,26 @@
442446
<td>
443447
<ul class="list-unstyled hstack gap-1 mb-0">
444448
<li data-bs-toggle="tooltip" data-bs-placement="top" title="View Detail">
445-
<Link href="page/conversation/{conv.id}" class="btn btn-sm btn-soft-primary">
446-
<i class="mdi mdi-eye-outline" />
447-
</Link>
449+
<Button
450+
class="btn btn-sm btn-soft-primary"
451+
on:click={() => window.open(`page/conversation/${conv.id}`)}
452+
>
453+
<i class="mdi mdi-eye-outline" />
454+
</Button>
448455
</li>
449456
<li data-bs-toggle="tooltip" data-bs-placement="top" title="Chat">
450-
<Link href="chat/{conv.agent_id}/{conv.id}" target="_blank" class="btn btn-sm btn-soft-info">
457+
<Button
458+
class="btn btn-sm btn-soft-info"
459+
on:click={() => window.open(`chat/${conv.agent_id}/${conv.id}`)}
460+
>
451461
<i class="mdi mdi-chat" />
452-
</Link>
462+
</Button>
453463
</li>
454464
<li data-bs-toggle="tooltip" data-bs-placement="top" title="Delete">
455-
<Button on:click={() => openDeleteModal(conv.id)} class="btn btn-sm btn-soft-danger">
465+
<Button
466+
class="btn btn-sm btn-soft-danger"
467+
on:click={() => openDeleteModal(conv.id)}
468+
>
456469
<i class="mdi mdi-delete-outline" />
457470
</Button>
458471
</li>

0 commit comments

Comments
 (0)