Skip to content

Commit

Permalink
Merge pull request #186 from iceljc/features/refine-knowledge-window
Browse files Browse the repository at this point in the history
Features/refine knowledge window
  • Loading branch information
iceljc authored Aug 12, 2024
2 parents e7a82b1 + ddc9bdd commit 199a335
Show file tree
Hide file tree
Showing 18 changed files with 729 additions and 142 deletions.
5 changes: 4 additions & 1 deletion src/lib/common/Loader.svelte
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
<script>
import { Circle } from 'svelte-loading-spinners';
export let disableDefaultStyles = false;
export let containerClasses = '';
export let size = 100;
</script>

<div class="loader">
<div class="{disableDefaultStyles ? '' : 'loader'} {containerClasses}">
<Circle {size} color="var(--bs-primary)" unit="px" duration="1s" />
</div>
4 changes: 3 additions & 1 deletion src/lib/helpers/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,6 @@ export const FILE_EDITORS = [
];

export const LERNER_ID = "01acc3e5-0af7-49e6-ad7a-a760bd12dc40";
export const TRAINING_MODE = "training";
export const TRAINING_MODE = "training";

export const KNOWLEDGE_COLLECTION = "BotSharp";
4 changes: 3 additions & 1 deletion src/lib/helpers/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ axios.interceptors.response.use(
function skipLoader(config) {
const postRegexes = [
new RegExp('http(s*)://(.*?)/conversation/(.*?)/(.*?)', 'g'),
new RegExp('http(s*)://(.*?)/agent', 'g')
new RegExp('http(s*)://(.*?)/agent', 'g'),
new RegExp('http(s*)://(.*?)/knowledge/(.*?)/data', 'g'),
new RegExp('http(s*)://(.*?)/knowledge/(.*?)/search', 'g')
];

const getRegexes = [
Expand Down
48 changes: 44 additions & 4 deletions src/lib/helpers/types/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,13 @@


// File models
/**
* @typedef {Object} FileModel
* @property {string} file_name - The file name.
* @property {string} file_data - The file data.
* @property {string} file_url - The file url.
*/

/**
* @typedef {Object} TextFileModel
* @property {string} file_name - The file name.
Expand Down Expand Up @@ -453,13 +460,46 @@ IRichContent.prototype.quick_replies;
* @property {string?} [payload] - The payload message.
*/

// Knowledgebase
/**
* @typedef {Object} FileModel
* @property {string} file_name - The plugin full name.
* @property {string} file_data - The plugin name.
* @property {string} file_url - Row count.
* @typedef {Object} SearchKnowledgeRequest
* @property {string} text - The text.
* @property {string} [fields] - Data fields.
* @property {number} [limit] - Data limit.
* @property {number} [confidence] - Confidence.
* @property {boolean} [with_vector] - Include vector or not.
*/

/**
* @typedef {Object} KnowledgeFilter
* @property {string | null} [start_id] - The start id.
* @property {number} size - Page size.
* @property {boolean} [with_vector] - Include vector or not.
*/

/**
* @typedef {Object} KnowledgeRetrivalViewModel
* @property {any} data - The knowledge data.
* @property {number} score - The knowledge score.
* @property {number[]} [vector] - The knowledge vector.
*/

/**
* @typedef {Object} KnowledgeCollectionDataViewModel
* @property {string} id - The knowledge data id.
* @property {string} question - The question.
* @property {string} answer - The answer.
* @property {number[]} [vector] - The knowledge vector.
*/

/**
* @typedef {Object} KnowledgeCollectionDataResult
* @property {number} count - The total data count.
* @property {KnowledgeCollectionDataViewModel[]} items - The data items.
* @property {string} [next_id] - The next id.
*/


/**
* Invoked when a new conersation is created.
* This callback type is called `requestCallback` and is displayed as a global symbol.
Expand Down
1 change: 1 addition & 0 deletions src/lib/scss/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ File: Main Css File
@import "custom/pages/jobs";
@import "custom/pages/conversation";
@import "custom/pages/agent";
@import "custom/pages/knowledgebase";

// Common
@import "custom/common/animation";
Expand Down
111 changes: 111 additions & 0 deletions src/lib/scss/custom/pages/_knowledgebase.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
.knowledge-demo-btn {
display: flex;
justify-content: flex-start;
gap: 10px;

.btn-content {
display: flex;
justify-content: center;
gap: 3px;
flex-wrap: wrap;
}

.btn-icon {
display: flex;
flex-direction: column;
justify-content: center;
}

.demo-tip {
font-size: 18px;
}
}

.knowledge-search-container {
.search-textarea {
border-radius: 5px;
border-color: var(--#{$prefix}light) !important;
background-color: var(--#{$prefix}light) !important;
scrollbar-width: thin;
}

.text-count {
margin-top: 2px;
font-size: 10px;
}

.knowledge-search-result-container {
.list-open {
list-style-type: disclosure-open;
}

.list-closed {
list-style-type: disclosure-closed;
}

.result-item {
margin: 5px 0px;
font-size: 15px;

.result-key {
font-size: 17px;
}

.result-content {
word-break: normal;
}

.result-score {
margin-top: 5px;
}
}
}
}

.knowledge-table {
overflow: hidden;

.knowledge-text {
width: 40%;
max-width: 50px;

.ellipsis {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}

.knowledge-op {
width: 20%;

.knowledge-op-list {
justify-content: center;
}
}

.knowledge-detail {
padding: 2px 5px;
border-radius: 3px;
border-color: var(--#{$prefix}light) !important;
background-color: var(--#{$prefix}light) !important;

ul {
margin: 15px 0px;
list-style-type: square;

li {
margin: 5px 0px;
}
}

.wrappable {
white-space: wrap !important;
}
}
}

.knowledge-loader {
display: flex;
justify-content: center;
}
5 changes: 4 additions & 1 deletion src/lib/services/api-endpoints.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ export const endpoints = {
loggingStateLogUrl: `${host}/logger/conversation/{conversationId}/state-log`,

// knowledge base
knowledgeBaseUploadUrl: `${host}/knowledge-base/upload`,
knowledgeBaseUploadUrl: `${host}/knowledge/{collection}/upload`,
knowledgeBaseDataListUrl: `${host}/knowledge/{collection}/data`,
knowledgeBaseSearchUrl: `${host}/knowledge/{collection}/search`,
knowledgeBaseDeleteDataUrl: `${host}/knowledge/{collection}/data/{id}`,

// chathub
chatHubUrl: `${host}/chatHub`,
Expand Down
70 changes: 67 additions & 3 deletions src/lib/services/knowledge-base-service.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,81 @@
import { KNOWLEDGE_COLLECTION } from '$lib/helpers/constants.js';
import { replaceUrl } from '$lib/helpers/http.js';
import { endpoints } from './api-endpoints.js';
import axios from 'axios';

/**
* @param {import('$types').SearchKnowledgeRequest} request
* @param {string | null} [collection]
* @returns {Promise<import('$types').KnowledgeRetrivalViewModel[]>}
*/
export async function searchKnowledge(request, collection = null) {
const url = replaceUrl(endpoints.knowledgeBaseSearchUrl, {
collection: collection || KNOWLEDGE_COLLECTION
});

const body = {
...request,
fields: request.fields || ["text", "answer"]
};
const response = await axios.post(url, { ...body });
return response.data;
}

/**
* @param {import('$types').KnowledgeFilter} filter
* @param {string | null} [collection]
* @returns {Promise<import('$types').KnowledgeCollectionDataResult>}
*/
export async function getKnowledgeData(filter, collection = null) {
const url = replaceUrl(endpoints.knowledgeBaseDataListUrl, {
collection: collection || KNOWLEDGE_COLLECTION
});

const response = await axios.post(url, { ...filter });
return response.data;
}


/**
* @param {string} id
* @param {string | null} [collection]
* @returns {Promise<boolean>}
*/
export async function deleteKnowledgeData(id, collection = null) {
const url = replaceUrl(endpoints.knowledgeBaseDeleteDataUrl, {
collection: collection || KNOWLEDGE_COLLECTION,
id: id
});

const response = await axios.delete(url);
return response.data;
}


/**
* Upload document to knowledge base.
* @param {File} file
* @param {string | null} [collection]
* @param {number | null} [startPageNum]
* @param {number | null} [endPageNum]
*/
export async function uploadDocument(file) {
let url = endpoints.knowledgeBaseUploadUrl;
export async function uploadKnowledge(file, collection = null, startPageNum = null, endPageNum = null) {
const url = replaceUrl(endpoints.knowledgeBaseUploadUrl, {
collection: collection || KNOWLEDGE_COLLECTION
});

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

let config = {
if (startPageNum) {
formData.append("startPageNum", startPageNum.toString());
}

if (endPageNum) {
formData.append("endPageNum", endPageNum.toString());
}

const config = {
headers: {
"Content-Type": "multipart/form-data"
}
Expand Down
29 changes: 21 additions & 8 deletions src/routes/page/conversation/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import StateModal from '$lib/common/StateModal.svelte';
import { conversationSearchOptionStore } from '$lib/helpers/store';
import { onMount } from 'svelte';
import Link from 'svelte-link';
import { getAgents } from '$lib/services/agent-service';
import { getConversations, deleteConversation } from '$lib/services/conversation-service.js';
import { utcToLocal } from '$lib/helpers/datetime';
Expand Down Expand Up @@ -347,7 +346,12 @@
<div class="d-flex align-items-center">
<h5 class="mb-0 card-title flex-grow-1">{$_('Conversation List')}</h5>
<div class="flex-shrink-0">
<Link class="btn btn-light" on:click={(e) => searchConversations(e)}><i class="mdi mdi-magnify" /></Link>
<Button
class="btn btn-light"
on:click={(e) => searchConversations(e)}
>
<i class="mdi mdi-magnify" />
</Button>
<Dropdown class="dropdown d-inline-block">
<DropdownToggle type="menu" class="btn" id="dropdownMenuButton1">
<i class="mdi mdi-dots-vertical" />
Expand Down Expand Up @@ -442,17 +446,26 @@
<td>
<ul class="list-unstyled hstack gap-1 mb-0">
<li data-bs-toggle="tooltip" data-bs-placement="top" title="View Detail">
<Link href="page/conversation/{conv.id}" class="btn btn-sm btn-soft-primary">
<i class="mdi mdi-eye-outline" />
</Link>
<Button
class="btn btn-sm btn-soft-primary"
on:click={() => window.open(`page/conversation/${conv.id}`)}
>
<i class="mdi mdi-eye-outline" />
</Button>
</li>
<li data-bs-toggle="tooltip" data-bs-placement="top" title="Chat">
<Link href="chat/{conv.agent_id}/{conv.id}" target="_blank" class="btn btn-sm btn-soft-info">
<Button
class="btn btn-sm btn-soft-info"
on:click={() => window.open(`chat/${conv.agent_id}/${conv.id}`)}
>
<i class="mdi mdi-chat" />
</Link>
</Button>
</li>
<li data-bs-toggle="tooltip" data-bs-placement="top" title="Delete">
<Button on:click={() => openDeleteModal(conv.id)} class="btn btn-sm btn-soft-danger">
<Button
class="btn btn-sm btn-soft-danger"
on:click={() => openDeleteModal(conv.id)}
>
<i class="mdi mdi-delete-outline" />
</Button>
</li>
Expand Down
Loading

0 comments on commit 199a335

Please sign in to comment.