diff --git a/backend/open_webui/apps/webui/models/chats.py b/backend/open_webui/apps/webui/models/chats.py index 62e4d2755..55b4a9054 100644 --- a/backend/open_webui/apps/webui/models/chats.py +++ b/backend/open_webui/apps/webui/models/chats.py @@ -480,7 +480,18 @@ class ChatTable: ) # Check if there are any tags to filter, it should have all the tags - if tag_ids: + if "none" in tag_ids: + query = query.filter( + text( + """ + NOT EXISTS ( + SELECT 1 + FROM json_each(Chat.meta, '$.tags') AS tag + ) + """ + ) + ) + elif tag_ids: query = query.filter( and_( *[ @@ -518,7 +529,18 @@ class ChatTable: ) # Check if there are any tags to filter, it should have all the tags - if tag_ids: + if "none" in tag_ids: + query = query.filter( + text( + """ + NOT EXISTS ( + SELECT 1 + FROM json_array_elements_text(Chat.meta->'tags') AS tag + ) + """ + ) + ) + elif tag_ids: query = query.filter( and_( *[ diff --git a/src/lib/components/layout/Sidebar.svelte b/src/lib/components/layout/Sidebar.svelte index 1bd4632c9..b12641ebe 100644 --- a/src/lib/components/layout/Sidebar.svelte +++ b/src/lib/components/layout/Sidebar.svelte @@ -197,6 +197,7 @@ return; } else { searchDebounceTimeout = setTimeout(async () => { + allChatsLoaded = false; currentChatPage.set(1); await chats.set(await getChatListBySearchText(localStorage.token, search)); diff --git a/src/lib/components/layout/Sidebar/SearchInput.svelte b/src/lib/components/layout/Sidebar/SearchInput.svelte index 156974e9e..608ba7ce0 100644 --- a/src/lib/components/layout/Sidebar/SearchInput.svelte +++ b/src/lib/components/layout/Sidebar/SearchInput.svelte @@ -30,7 +30,13 @@ let filteredTags = []; $: filteredTags = lastWord.startsWith('tag:') - ? $tags.filter((tag) => { + ? [ + ...$tags, + { + id: 'none', + name: $i18n.t('Untagged') + } + ].filter((tag) => { const tagName = lastWord.slice(4); if (tagName) { const tagId = tagName.replace(' ', '_').toLowerCase();