瀏覽代碼

enh: reset models

Timothy Jaeryang Baek 5 月之前
父節點
當前提交
81bb2750e0

+ 10 - 0
backend/open_webui/apps/webui/models/models.py

@@ -257,5 +257,15 @@ class ModelsTable:
         except Exception:
             return False
 
+    def delete_all_models(self) -> bool:
+        try:
+            with get_db() as db:
+                db.query(Model).delete()
+                db.commit()
+
+                return True
+        except Exception:
+            return False
+
 
 Models = ModelsTable()

+ 6 - 0
backend/open_webui/apps/webui/routers/models.py

@@ -180,3 +180,9 @@ async def delete_model_by_id(id: str, user=Depends(get_verified_user)):
 
     result = Models.delete_model_by_id(id)
     return result
+
+
+@router.delete("/delete/all", response_model=bool)
+async def delete_all_models(user=Depends(get_admin_user)):
+    result = Models.delete_all_models()
+    return result

+ 33 - 0
src/lib/apis/models/index.ts

@@ -231,3 +231,36 @@ export const deleteModelById = async (token: string, id: string) => {
 
 	return res;
 };
+
+
+export const deleteAllModels = async (token: string) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/models/delete/all`, {
+		method: 'DELETE',
+		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;
+
+			console.log(err);
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};

+ 32 - 1
src/lib/components/admin/Settings/Models.svelte

@@ -9,6 +9,7 @@
 	import { WEBUI_NAME, config, mobile, models as _models, settings, user } from '$lib/stores';
 	import {
 		createNewModel,
+		deleteAllModels,
 		getBaseModels,
 		toggleModelById,
 		updateModelById
@@ -22,6 +23,7 @@
 
 	import ModelEditor from '$lib/components/workspace/Models/ModelEditor.svelte';
 	import { toast } from 'svelte-sonner';
+	import ConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
 
 	let importFiles;
 	let modelsImportInputElement: HTMLInputElement;
@@ -32,8 +34,8 @@
 	let baseModels = null;
 
 	let filteredModels = [];
-
 	let selectedModelId = null;
+	let showResetModal = false;
 
 	$: if (models) {
 		filteredModels = models.filter(
@@ -126,6 +128,19 @@
 	});
 </script>
 
+<ConfirmDialog
+	title={$i18n.t('Delete All Models')}
+	message={$i18n.t('This will delete all models including custom models and cannot be undone.')}
+	bind:show={showResetModal}
+	onConfirm={async () => {
+		const res = deleteAllModels(localStorage.token);
+		if (res) {
+			toast.success($i18n.t('All models deleted successfully'));
+			init();
+		}
+	}}
+/>
+
 {#if models !== null}
 	{#if selectedModelId === null}
 		<div class="flex flex-col gap-1 mt-1.5 mb-2">
@@ -137,6 +152,22 @@
 						>{filteredModels.length}</span
 					>
 				</div>
+
+				<div>
+					<Tooltip content={$i18n.t('This will delete all models including custom models')}>
+						<button
+							class=" px-2.5 py-1 rounded-full flex gap-1 items-center"
+							type="button"
+							on:click={() => {
+								showResetModal = true;
+							}}
+						>
+							<div class="text-sm flex-shrink-0">
+								{$i18n.t('Reset')}
+							</div>
+						</button>
+					</Tooltip>
+				</div>
 			</div>
 
 			<div class=" flex flex-1 items-center w-full space-x-2">

+ 11 - 4
src/lib/components/common/ConfirmDialog.svelte

@@ -12,6 +12,8 @@
 	export let cancelLabel = $i18n.t('Cancel');
 	export let confirmLabel = $i18n.t('Confirm');
 
+	export let onConfirm = () => {};
+
 	export let input = false;
 	export let inputPlaceholder = '';
 	export let inputValue = '';
@@ -29,11 +31,17 @@
 
 		if (event.key === 'Enter') {
 			console.log('Enter');
-			show = false;
-			dispatch('confirm', inputValue);
+			confirmHandler();
 		}
 	};
 
+	const confirmHandler = async () => {
+		show = false;
+
+		await onConfirm();
+		dispatch('confirm', inputValue);
+	};
+
 	onMount(() => {
 		mounted = true;
 	});
@@ -110,8 +118,7 @@
 					<button
 						class="bg-gray-900 hover:bg-gray-850 text-gray-100 dark:bg-gray-100 dark:hover:bg-white dark:text-gray-800 font-medium w-full py-2.5 rounded-lg transition"
 						on:click={() => {
-							show = false;
-							dispatch('confirm', inputValue);
+							confirmHandler();
 						}}
 						type="button"
 					>