From a909aa1c2037771daa7648fa9fb11350a6ed8f36 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Fri, 4 Oct 2024 18:44:57 -0700 Subject: [PATCH] enh: sync directory --- .../apps/webui/routers/knowledge.py | 19 +++++++++++ src/lib/apis/knowledge/index.ts | 32 +++++++++++++++++++ src/lib/components/icons/ArrowPath.svelte | 19 +++++++++++ .../workspace/Knowledge/Collection.svelte | 25 +++++++++++++-- .../Collection/AddContentMenu.svelte | 26 ++++++++++----- 5 files changed, 110 insertions(+), 11 deletions(-) create mode 100644 src/lib/components/icons/ArrowPath.svelte diff --git a/backend/open_webui/apps/webui/routers/knowledge.py b/backend/open_webui/apps/webui/routers/knowledge.py index 4a73f1528..a792c24fa 100644 --- a/backend/open_webui/apps/webui/routers/knowledge.py +++ b/backend/open_webui/apps/webui/routers/knowledge.py @@ -313,6 +313,25 @@ def remove_file_from_knowledge_by_id( ) +############################ +# ResetKnowledgeById +############################ + + +@router.post("/{id}/reset", response_model=Optional[KnowledgeResponse]) +async def reset_knowledge_by_id(id: str, user=Depends(get_admin_user)): + try: + VECTOR_DB_CLIENT.delete_collection(collection_name=id) + except Exception as e: + log.debug(e) + pass + + knowledge = Knowledges.update_knowledge_by_id( + id=id, form_data=KnowledgeUpdateForm(data={"file_ids": []}) + ) + return knowledge + + ############################ # DeleteKnowledgeById ############################ diff --git a/src/lib/apis/knowledge/index.ts b/src/lib/apis/knowledge/index.ts index 9923624a6..842866899 100644 --- a/src/lib/apis/knowledge/index.ts +++ b/src/lib/apis/knowledge/index.ts @@ -243,6 +243,38 @@ export const removeFileFromKnowledgeById = async (token: string, id: string, fil return res; }; +export const resetKnowledgeById = async (token: string, id: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/knowledge/${id}/reset`, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + authorization: `Bearer ${token}` + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .then((json) => { + return json; + }) + .catch((err) => { + error = err.detail; + + console.log(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + export const deleteKnowledgeById = async (token: string, id: string) => { let error = null; diff --git a/src/lib/components/icons/ArrowPath.svelte b/src/lib/components/icons/ArrowPath.svelte new file mode 100644 index 000000000..5b31652d6 --- /dev/null +++ b/src/lib/components/icons/ArrowPath.svelte @@ -0,0 +1,19 @@ + + + + + diff --git a/src/lib/components/workspace/Knowledge/Collection.svelte b/src/lib/components/workspace/Knowledge/Collection.svelte index 275cc5283..a0500d3a6 100644 --- a/src/lib/components/workspace/Knowledge/Collection.svelte +++ b/src/lib/components/workspace/Knowledge/Collection.svelte @@ -14,6 +14,7 @@ addFileToKnowledgeById, getKnowledgeById, removeFileFromKnowledgeById, + resetKnowledgeById, updateFileFromKnowledgeById, updateKnowledgeById } from '$lib/apis/knowledge'; @@ -70,10 +71,12 @@ let selectedFileId = null; $: if (selectedFileId) { - const file = knowledge.files.find((file) => file.id === selectedFileId); + const file = (knowledge?.files ?? []).find((file) => file.id === selectedFileId); if (file) { file.data = file.data ?? { content: '' }; selectedFile = file; + } else { + selectedFile = null; } } else { selectedFile = null; @@ -130,6 +133,9 @@ // Get directory handle through picker const dirHandle = await window.showDirectoryPicker(); + console.log(typeof dirHandle); + console.log(dirHandle); + let totalFiles = 0; let uploadedFiles = 0; @@ -196,8 +202,18 @@ }; // Helper function to maintain file paths within zip - const getRelativePath = (fullPath, basePath) => { - return fullPath.substring(basePath.length + 1); + const syncDirectoryHandler = async () => { + const res = await resetKnowledgeById(localStorage.token, id).catch((e) => { + toast.error(e); + }); + + if (res) { + knowledge = res; + toast.success($i18n.t('Knowledge reset successfully.')); + + // Upload directory + uploadDirectoryHandler(); + } }; const addFileHandler = async (fileId) => { @@ -501,6 +517,9 @@ document.getElementById('files-input').click(); } }} + on:sync={(e) => { + syncDirectoryHandler(); + }} /> diff --git a/src/lib/components/workspace/Knowledge/Collection/AddContentMenu.svelte b/src/lib/components/workspace/Knowledge/Collection/AddContentMenu.svelte index 245793979..fa1f6d9c8 100644 --- a/src/lib/components/workspace/Knowledge/Collection/AddContentMenu.svelte +++ b/src/lib/components/workspace/Knowledge/Collection/AddContentMenu.svelte @@ -5,18 +5,11 @@ const dispatch = createEventDispatcher(); import Dropdown from '$lib/components/common/Dropdown.svelte'; - import GarbageBin from '$lib/components/icons/GarbageBin.svelte'; - import Pencil from '$lib/components/icons/Pencil.svelte'; import Tooltip from '$lib/components/common/Tooltip.svelte'; - import Tags from '$lib/components/chat/Tags.svelte'; - import Share from '$lib/components/icons/Share.svelte'; - import ArchiveBox from '$lib/components/icons/ArchiveBox.svelte'; - import DocumentDuplicate from '$lib/components/icons/DocumentDuplicate.svelte'; - import ArrowDownTray from '$lib/components/icons/ArrowDownTray.svelte'; import ArrowUpCircle from '$lib/components/icons/ArrowUpCircle.svelte'; - import EllipsisHorizontal from '$lib/components/icons/EllipsisHorizontal.svelte'; import BarsArrowUp from '$lib/components/icons/BarsArrowUp.svelte'; import FolderOpen from '$lib/components/icons/FolderOpen.svelte'; + import ArrowPath from '$lib/components/icons/ArrowPath.svelte'; const i18n = getContext('i18n'); @@ -83,6 +76,23 @@
{$i18n.t('Upload directory')}
+ + { + dispatch('sync', { type: 'directory' }); + }} + > + +
{$i18n.t('Sync directory')}
+
+
+ {