Browse Source

Merge pull request #910 from open-webui/dev

0.1.104
Timothy Jaeryang Baek 1 year ago
parent
commit
3c10c3b928

+ 11 - 0
CHANGELOG.md

@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
 
+## [0.1.104] - 2024-02-25
+
+### Added
+
+- **🔄 Check for Updates**: Keep your system current by checking for updates conveniently located in Settings > About.
+- **🗑️ Automatic Tag Deletion**: Unused tags on the sidebar will now be deleted automatically with just a click.
+
+### Changed
+
+- **🎨 Modernized Styling**: Enjoy a refreshed look with updated styling for a more contemporary experience.
+
 ## [0.1.103] - 2024-02-25
 ## [0.1.103] - 2024-02-25
 
 
 ### Added
 ### Added

+ 21 - 0
backend/apps/web/models/tags.py

@@ -167,6 +167,27 @@ class TagTable:
             .count()
             .count()
         )
         )
 
 
+    def delete_tag_by_tag_name_and_user_id(self, tag_name: str, user_id: str) -> bool:
+        try:
+            query = ChatIdTag.delete().where(
+                (ChatIdTag.tag_name == tag_name) & (ChatIdTag.user_id == user_id)
+            )
+            res = query.execute()  # Remove the rows, return number of rows removed.
+            print(res)
+
+            tag_count = self.count_chat_ids_by_tag_name_and_user_id(tag_name, user_id)
+            if tag_count == 0:
+                # Remove tag item from Tag col as well
+                query = Tag.delete().where(
+                    (Tag.name == tag_name) & (Tag.user_id == user_id)
+                )
+                query.execute()  # Remove the rows, return number of rows removed.
+
+            return True
+        except Exception as e:
+            print("delete_tag", e)
+            return False
+
     def delete_tag_by_tag_name_and_chat_id_and_user_id(
     def delete_tag_by_tag_name_and_chat_id_and_user_id(
         self, tag_name: str, chat_id: str, user_id: str
         self, tag_name: str, chat_id: str, user_id: str
     ) -> bool:
     ) -> bool:

+ 5 - 2
backend/apps/web/routers/chats.py

@@ -115,9 +115,12 @@ async def get_user_chats_by_tag_name(
         for chat_id_tag in Tags.get_chat_ids_by_tag_name_and_user_id(tag_name, user.id)
         for chat_id_tag in Tags.get_chat_ids_by_tag_name_and_user_id(tag_name, user.id)
     ]
     ]
 
 
-    print(chat_ids)
+    chats = Chats.get_chat_lists_by_chat_ids(chat_ids, skip, limit)
 
 
-    return Chats.get_chat_lists_by_chat_ids(chat_ids, skip, limit)
+    if len(chats) == 0:
+        Tags.delete_tag_by_tag_name_and_user_id(tag_name, user.id)
+
+    return chats
 
 
 
 
 ############################
 ############################

+ 1 - 0
backend/constants.py

@@ -47,3 +47,4 @@ class ERROR_MESSAGES(str, Enum):
     INCORRECT_FORMAT = (
     INCORRECT_FORMAT = (
         lambda err="": f"Invalid format. Please use the correct format{err if err else ''}"
         lambda err="": f"Invalid format. Please use the correct format{err if err else ''}"
     )
     )
+    RATE_LIMIT_EXCEEDED = "API rate limit exceeded"

+ 21 - 1
backend/main.py

@@ -4,8 +4,9 @@ import markdown
 import time
 import time
 import os
 import os
 import sys
 import sys
+import requests
 
 
-from fastapi import FastAPI, Request, Depends
+from fastapi import FastAPI, Request, Depends, status
 from fastapi.staticfiles import StaticFiles
 from fastapi.staticfiles import StaticFiles
 from fastapi import HTTPException
 from fastapi import HTTPException
 from fastapi.responses import JSONResponse
 from fastapi.responses import JSONResponse
@@ -26,6 +27,8 @@ from apps.web.main import app as webui_app
 
 
 
 
 from config import WEBUI_NAME, ENV, VERSION, CHANGELOG, FRONTEND_BUILD_DIR
 from config import WEBUI_NAME, ENV, VERSION, CHANGELOG, FRONTEND_BUILD_DIR
+from constants import ERROR_MESSAGES
+
 from utils.utils import get_http_authorization_cred, get_current_user
 from utils.utils import get_http_authorization_cred, get_current_user
 
 
 
 
@@ -127,6 +130,23 @@ async def get_app_changelog():
     return CHANGELOG
     return CHANGELOG
 
 
 
 
+@app.get("/api/version/updates")
+async def get_app_latest_release_version():
+    try:
+        response = requests.get(
+            f"https://api.github.com/repos/open-webui/open-webui/releases/latest"
+        )
+        response.raise_for_status()
+        latest_version = response.json()["tag_name"]
+
+        return {"current": VERSION, "latest": latest_version[1:]}
+    except Exception as e:
+        raise HTTPException(
+            status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
+            detail=ERROR_MESSAGES.RATE_LIMIT_EXCEEDED,
+        )
+
+
 app.mount("/static", StaticFiles(directory="static"), name="static")
 app.mount("/static", StaticFiles(directory="static"), name="static")
 
 
 
 

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
 {
 	"name": "open-webui",
 	"name": "open-webui",
-	"version": "0.1.103",
+	"version": "0.1.104",
 	"private": true,
 	"private": true,
 	"scripts": {
 	"scripts": {
 		"dev": "vite dev --host",
 		"dev": "vite dev --host",

+ 34 - 0
src/lib/apis/index.ts

@@ -19,6 +19,10 @@ export const getBackendConfig = async () => {
 			return null;
 			return null;
 		});
 		});
 
 
+	if (error) {
+		throw error;
+	}
+
 	return res;
 	return res;
 };
 };
 
 
@@ -41,5 +45,35 @@ export const getChangelog = async () => {
 			return null;
 			return null;
 		});
 		});
 
 
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
+export const getVersionUpdates = async () => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_BASE_URL}/api/version/updates`, {
+		method: 'GET',
+		headers: {
+			'Content-Type': 'application/json'
+		}
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.catch((err) => {
+			console.log(err);
+			error = err;
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
 	return res;
 	return res;
 };
 };

+ 12 - 14
src/lib/components/chat/MessageInput.svelte

@@ -490,7 +490,7 @@
 					}}
 					}}
 				/>
 				/>
 				<form
 				<form
-					class=" flex flex-col relative w-full rounded-xl border dark:border-gray-700 bg-white dark:bg-gray-900 dark:text-gray-100"
+					class=" flex flex-col relative w-full rounded-3xl px-1.5 border border-gray-100 dark:border-gray-850 bg-white dark:bg-gray-900 dark:text-gray-100"
 					on:submit|preventDefault={() => {
 					on:submit|preventDefault={() => {
 						submitPrompt(prompt, user);
 						submitPrompt(prompt, user);
 					}}
 					}}
@@ -633,9 +633,9 @@
 
 
 					<div class=" flex">
 					<div class=" flex">
 						{#if fileUploadEnabled}
 						{#if fileUploadEnabled}
-							<div class=" self-end mb-2 ml-1.5">
+							<div class=" self-end mb-2 ml-1">
 								<button
 								<button
-									class="  text-gray-600 dark:text-gray-200 transition rounded-lg p-1 ml-1"
+									class="bg-gray-50 hover:bg-gray-100 text-gray-800 dark:bg-gray-850 dark:text-white dark:hover:bg-gray-800 transition rounded-full p-1.5"
 									type="button"
 									type="button"
 									on:click={() => {
 									on:click={() => {
 										filesInputElement.click();
 										filesInputElement.click();
@@ -643,14 +643,12 @@
 								>
 								>
 									<svg
 									<svg
 										xmlns="http://www.w3.org/2000/svg"
 										xmlns="http://www.w3.org/2000/svg"
-										viewBox="0 0 20 20"
+										viewBox="0 0 16 16"
 										fill="currentColor"
 										fill="currentColor"
-										class="w-5 h-5"
+										class="w-[1.2rem] h-[1.2rem]"
 									>
 									>
 										<path
 										<path
-											fill-rule="evenodd"
-											d="M15.621 4.379a3 3 0 00-4.242 0l-7 7a3 3 0 004.241 4.243h.001l.497-.5a.75.75 0 011.064 1.057l-.498.501-.002.002a4.5 4.5 0 01-6.364-6.364l7-7a4.5 4.5 0 016.368 6.36l-3.455 3.553A2.625 2.625 0 119.52 9.52l3.45-3.451a.75.75 0 111.061 1.06l-3.45 3.451a1.125 1.125 0 001.587 1.595l3.454-3.553a3 3 0 000-4.242z"
-											clip-rule="evenodd"
+											d="M8.75 3.75a.75.75 0 0 0-1.5 0v3.5h-3.5a.75.75 0 0 0 0 1.5h3.5v3.5a.75.75 0 0 0 1.5 0v-3.5h3.5a.75.75 0 0 0 0-1.5h-3.5v-3.5Z"
 										/>
 										/>
 									</svg>
 									</svg>
 								</button>
 								</button>
@@ -659,7 +657,7 @@
 
 
 						<textarea
 						<textarea
 							id="chat-textarea"
 							id="chat-textarea"
-							class=" dark:bg-gray-900 dark:text-gray-100 outline-none w-full py-3 px-2 {fileUploadEnabled
+							class=" dark:bg-gray-900 dark:text-gray-100 outline-none w-full py-3 px-3 {fileUploadEnabled
 								? ''
 								? ''
 								: ' pl-4'} rounded-xl resize-none h-[48px]"
 								: ' pl-4'} rounded-xl resize-none h-[48px]"
 							placeholder={chatInputPlaceholder !== ''
 							placeholder={chatInputPlaceholder !== ''
@@ -803,12 +801,12 @@
 							}}
 							}}
 						/>
 						/>
 
 
-						<div class="self-end mb-2 flex space-x-0.5 mr-2">
+						<div class="self-end mb-2 flex space-x-1 mr-1">
 							{#if messages.length == 0 || messages.at(-1).done == true}
 							{#if messages.length == 0 || messages.at(-1).done == true}
 								{#if speechRecognitionEnabled}
 								{#if speechRecognitionEnabled}
 									<button
 									<button
 										id="voice-input-button"
 										id="voice-input-button"
-										class=" text-gray-600 dark:text-gray-300 transition rounded-lg p-1.5 mr-0.5 self-center"
+										class=" text-gray-600 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-850 transition rounded-full p-1.5 mr-0.5 self-center"
 										type="button"
 										type="button"
 										on:click={() => {
 										on:click={() => {
 											speechRecognitionHandler();
 											speechRecognitionHandler();
@@ -869,7 +867,7 @@
 								<button
 								<button
 									class="{prompt !== ''
 									class="{prompt !== ''
 										? 'bg-black text-white hover:bg-gray-900 dark:bg-white dark:text-black dark:hover:bg-gray-100 '
 										? 'bg-black text-white hover:bg-gray-900 dark:bg-white dark:text-black dark:hover:bg-gray-100 '
-										: 'text-white bg-gray-100 dark:text-gray-900 dark:bg-gray-800 disabled'} transition rounded-lg p-1 mr-0.5 w-7 h-7 self-center"
+										: 'text-white bg-gray-100 dark:text-gray-900 dark:bg-gray-800 disabled'} transition rounded-full p-1.5 self-center"
 									type="submit"
 									type="submit"
 									disabled={prompt === ''}
 									disabled={prompt === ''}
 								>
 								>
@@ -877,7 +875,7 @@
 										xmlns="http://www.w3.org/2000/svg"
 										xmlns="http://www.w3.org/2000/svg"
 										viewBox="0 0 16 16"
 										viewBox="0 0 16 16"
 										fill="currentColor"
 										fill="currentColor"
-										class="w-4.5 h-4.5 mx-auto"
+										class="w-5 h-5"
 									>
 									>
 										<path
 										<path
 											fill-rule="evenodd"
 											fill-rule="evenodd"
@@ -888,7 +886,7 @@
 								</button>
 								</button>
 							{:else}
 							{:else}
 								<button
 								<button
-									class="bg-white hover:bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-800 transition rounded-lg p-1.5"
+									class="bg-white hover:bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-800 transition rounded-full p-1.5"
 									on:click={stopResponse}
 									on:click={stopResponse}
 								>
 								>
 									<svg
 									<svg

+ 40 - 38
src/lib/components/chat/MessageInput/Suggestions.svelte

@@ -10,45 +10,47 @@
 			: suggestionPrompts.sort(() => Math.random() - 0.5).slice(0, 4);
 			: suggestionPrompts.sort(() => Math.random() - 0.5).slice(0, 4);
 </script>
 </script>
 
 
-<div class=" flex flex-wrap-reverse mb-3 md:p-1 text-left w-full">
-	{#each prompts as prompt, promptIdx}
-		<div
-			class="{promptIdx > 1 ? 'hidden sm:inline-flex' : ''} basis-full sm:basis-1/2 p-[5px] px-2"
-		>
-			<button
-				class=" flex-1 flex justify-between w-full h-full px-4 py-2.5 bg-white hover:bg-gray-50 dark:bg-gray-900 dark:hover:bg-gray-700 outline outline-1 outline-gray-200 dark:outline-gray-800 rounded-lg transition group"
-				on:click={() => {
-					submitPrompt(prompt.content);
-				}}
+<div class=" mb-3 md:p-1 text-left w-full">
+	<div class=" flex flex-wrap-reverse px-2 text-left">
+		{#each prompts as prompt, promptIdx}
+			<div
+				class="{promptIdx > 1 ? 'hidden sm:inline-flex' : ''} basis-full sm:basis-1/2 p-[5px] px-1"
 			>
 			>
-				<div class="flex flex-col text-left self-center">
-					{#if prompt.title && prompt.title[0] !== ''}
-						<div class="text-sm font-medium dark:text-gray-300">{prompt.title[0]}</div>
-						<div class="text-sm text-gray-500 line-clamp-1">{prompt.title[1]}</div>
-					{:else}
-						<div class=" self-center text-sm font-medium dark:text-gray-300 line-clamp-2">
-							{prompt.content}
-						</div>
-					{/if}
-				</div>
-
-				<div
-					class="self-center p-1 rounded-lg text-white group-hover:bg-gray-100 group-hover:text-gray-800 dark:group-hover:bg-gray-800 dark:group-hover:text-gray-100 dark:text-gray-900 transition"
+				<button
+					class=" flex-1 flex justify-between w-full h-full px-4 py-2.5 bg-gray-50 hover:bg-gray-100 dark:bg-gray-850 dark:hover:bg-gray-800 rounded-2xl transition group"
+					on:click={() => {
+						submitPrompt(prompt.content);
+					}}
 				>
 				>
-					<svg
-						xmlns="http://www.w3.org/2000/svg"
-						viewBox="0 0 16 16"
-						fill="currentColor"
-						class="w-4 h-4"
+					<div class="flex flex-col text-left self-center">
+						{#if prompt.title && prompt.title[0] !== ''}
+							<div class="text-sm font-medium dark:text-gray-300">{prompt.title[0]}</div>
+							<div class="text-sm text-gray-500 line-clamp-1">{prompt.title[1]}</div>
+						{:else}
+							<div class=" self-center text-sm font-medium dark:text-gray-300 line-clamp-2">
+								{prompt.content}
+							</div>
+						{/if}
+					</div>
+
+					<div
+						class="self-center p-1 rounded-lg text-gray-50 group-hover:text-gray-800 dark:text-gray-850 dark:group-hover:text-gray-100 transition"
 					>
 					>
-						<path
-							fill-rule="evenodd"
-							d="M8 14a.75.75 0 0 1-.75-.75V4.56L4.03 7.78a.75.75 0 0 1-1.06-1.06l4.5-4.5a.75.75 0 0 1 1.06 0l4.5 4.5a.75.75 0 0 1-1.06 1.06L8.75 4.56v8.69A.75.75 0 0 1 8 14Z"
-							clip-rule="evenodd"
-						/>
-					</svg>
-				</div>
-			</button>
-		</div>
-	{/each}
+						<svg
+							xmlns="http://www.w3.org/2000/svg"
+							viewBox="0 0 16 16"
+							fill="currentColor"
+							class="w-4 h-4"
+						>
+							<path
+								fill-rule="evenodd"
+								d="M8 14a.75.75 0 0 1-.75-.75V4.56L4.03 7.78a.75.75 0 0 1-1.06-1.06l4.5-4.5a.75.75 0 0 1 1.06 0l4.5 4.5a.75.75 0 0 1-1.06 1.06L8.75 4.56v8.69A.75.75 0 0 1 8 14Z"
+								clip-rule="evenodd"
+							/>
+						</svg>
+					</div>
+				</button>
+			</div>
+		{/each}
+	</div>
 </div>
 </div>

+ 4 - 1
src/lib/components/chat/Messages/Placeholder.svelte

@@ -1,5 +1,6 @@
 <script lang="ts">
 <script lang="ts">
 	import { WEBUI_BASE_URL } from '$lib/constants';
 	import { WEBUI_BASE_URL } from '$lib/constants';
+	import { user } from '$lib/stores';
 	import { onMount } from 'svelte';
 	import { onMount } from 'svelte';
 
 
 	export let models = [];
 	export let models = [];
@@ -63,7 +64,9 @@
 					</div>
 					</div>
 				{/if}
 				{/if}
 			{:else}
 			{:else}
-				How can I help you today?
+				<div class=" line-clamp-1">Hello, {$user.name}</div>
+
+				<div>How can I help you today?</div>
 			{/if}
 			{/if}
 		</div>
 		</div>
 	</div>
 	</div>

+ 48 - 2
src/lib/components/chat/Settings/About.svelte

@@ -1,14 +1,40 @@
 <script lang="ts">
 <script lang="ts">
+	import { getVersionUpdates } from '$lib/apis';
 	import { getOllamaVersion } from '$lib/apis/ollama';
 	import { getOllamaVersion } from '$lib/apis/ollama';
 	import { WEBUI_VERSION } from '$lib/constants';
 	import { WEBUI_VERSION } from '$lib/constants';
 	import { WEBUI_NAME, config, showChangelog } from '$lib/stores';
 	import { WEBUI_NAME, config, showChangelog } from '$lib/stores';
+	import { compareVersion } from '$lib/utils';
 	import { onMount } from 'svelte';
 	import { onMount } from 'svelte';
 
 
 	let ollamaVersion = '';
 	let ollamaVersion = '';
+
+	let updateAvailable = null;
+	let version = {
+		current: '',
+		latest: ''
+	};
+
+	const checkForVersionUpdates = async () => {
+		updateAvailable = null;
+		version = await getVersionUpdates(localStorage.token).catch((error) => {
+			return {
+				current: WEBUI_VERSION,
+				latest: WEBUI_VERSION
+			};
+		});
+
+		console.log(version);
+
+		updateAvailable = compareVersion(version.latest, version.current);
+		console.log(updateAvailable);
+	};
+
 	onMount(async () => {
 	onMount(async () => {
 		ollamaVersion = await getOllamaVersion(localStorage.token).catch((error) => {
 		ollamaVersion = await getOllamaVersion(localStorage.token).catch((error) => {
 			return '';
 			return '';
 		});
 		});
+
+		checkForVersionUpdates();
 	});
 	});
 </script>
 </script>
 
 
@@ -20,10 +46,21 @@
 					{$WEBUI_NAME} Version
 					{$WEBUI_NAME} Version
 				</div>
 				</div>
 			</div>
 			</div>
-			<div class="flex w-full">
-				<div class="flex-1 text-xs text-gray-700 dark:text-gray-200 flex space-x-1.5 items-center">
+			<div class="flex w-full justify-between items-center">
+				<div class="flex flex-col text-xs text-gray-700 dark:text-gray-200">
 					<div>
 					<div>
 						v{WEBUI_VERSION}
 						v{WEBUI_VERSION}
+
+						<a
+							href="https://github.com/open-webui/open-webui/releases/tag/v{version.latest}"
+							target="_blank"
+						>
+							{updateAvailable === null
+								? 'Checking for updates...'
+								: updateAvailable
+								? `(v${version.latest} available!)`
+								: '(latest)'}
+						</a>
 					</div>
 					</div>
 
 
 					<button
 					<button
@@ -35,6 +72,15 @@
 						<div>See what's new</div>
 						<div>See what's new</div>
 					</button>
 					</button>
 				</div>
 				</div>
+
+				<button
+					class=" text-xs px-3 py-1.5 bg-gray-100 hover:bg-gray-200 dark:bg-gray-850 dark:hover:bg-gray-800 transition rounded-lg font-medium"
+					on:click={() => {
+						checkForVersionUpdates();
+					}}
+				>
+					Check for updates
+				</button>
 			</div>
 			</div>
 		</div>
 		</div>
 
 

+ 8 - 2
src/lib/components/layout/Sidebar.svelte

@@ -13,7 +13,8 @@
 		getChatList,
 		getChatList,
 		getChatById,
 		getChatById,
 		getChatListByTagName,
 		getChatListByTagName,
-		updateChatById
+		updateChatById,
+		getAllChatTags
 	} from '$lib/apis/chats';
 	} from '$lib/apis/chats';
 	import toast from 'svelte-french-toast';
 	import toast from 'svelte-french-toast';
 	import { slide } from 'svelte/transition';
 	import { slide } from 'svelte/transition';
@@ -330,7 +331,12 @@
 						<button
 						<button
 							class="px-2.5 text-xs font-medium bg-gray-900 hover:bg-gray-800 transition rounded-full"
 							class="px-2.5 text-xs font-medium bg-gray-900 hover:bg-gray-800 transition rounded-full"
 							on:click={async () => {
 							on:click={async () => {
-								await chats.set(await getChatListByTagName(localStorage.token, tag.name));
+								let chatIds = await getChatListByTagName(localStorage.token, tag.name);
+								if (chatIds.length === 0) {
+									await tags.set(await getAllChatTags(localStorage.token));
+									chatIds = await getChatList(localStorage.token);
+								}
+								await chats.set(chatIds);
 							}}
 							}}
 						>
 						>
 							{tag.name}
 							{tag.name}

+ 2 - 3
src/lib/utils/index.ts

@@ -101,11 +101,10 @@ export const copyToClipboard = (text) => {
 	);
 	);
 };
 };
 
 
-export const checkVersion = (required, current) => {
-	// Returns true when current version is below required
+export const compareVersion = (latest, current) => {
 	return current === '0.0.0'
 	return current === '0.0.0'
 		? false
 		? false
-		: current.localeCompare(required, undefined, {
+		: current.localeCompare(latest, undefined, {
 				numeric: true,
 				numeric: true,
 				sensitivity: 'case',
 				sensitivity: 'case',
 				caseFirst: 'upper'
 				caseFirst: 'upper'

+ 2 - 2
src/routes/(app)/+layout.svelte

@@ -28,7 +28,7 @@
 		config
 		config
 	} from '$lib/stores';
 	} from '$lib/stores';
 	import { REQUIRED_OLLAMA_VERSION, WEBUI_API_BASE_URL } from '$lib/constants';
 	import { REQUIRED_OLLAMA_VERSION, WEBUI_API_BASE_URL } from '$lib/constants';
-	import { checkVersion } from '$lib/utils';
+	import { compareVersion } from '$lib/utils';
 
 
 	import SettingsModal from '$lib/components/chat/SettingsModal.svelte';
 	import SettingsModal from '$lib/components/chat/SettingsModal.svelte';
 	import Sidebar from '$lib/components/layout/Sidebar.svelte';
 	import Sidebar from '$lib/components/layout/Sidebar.svelte';
@@ -79,7 +79,7 @@
 		ollamaVersion = version;
 		ollamaVersion = version;
 
 
 		console.log(ollamaVersion);
 		console.log(ollamaVersion);
-		if (checkVersion(REQUIRED_OLLAMA_VERSION, ollamaVersion)) {
+		if (compareVersion(REQUIRED_OLLAMA_VERSION, ollamaVersion)) {
 			toast.error(`Ollama Version: ${ollamaVersion !== '' ? ollamaVersion : 'Not Detected'}`);
 			toast.error(`Ollama Version: ${ollamaVersion !== '' ? ollamaVersion : 'Not Detected'}`);
 		}
 		}
 	};
 	};