diff --git a/backend/config.py b/backend/config.py index 33e5a25be..fa73a1f9e 100644 --- a/backend/config.py +++ b/backend/config.py @@ -31,7 +31,7 @@ if ENV == "prod": # WEBUI_VERSION #################################### -WEBUI_VERSION = os.environ.get("WEBUI_VERSION", "v1.0.0-alpha.11") +WEBUI_VERSION = os.environ.get("WEBUI_VERSION", "v1.0.0-alpha.21") #################################### # WEBUI_AUTH diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index 9a2e0f697..015e6e3a4 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -6,7 +6,7 @@ export let submitPrompt: Function; export let stopResponse: Function; - export let suggestions = 'true'; + export let suggestionPrompts = []; export let autoScroll = true; let filesInputElement; @@ -87,8 +87,8 @@
- {#if messages.length == 0 && suggestions !== 'false'} - + {#if messages.length == 0 && suggestionPrompts.length !== 0} + {/if} {#if autoScroll === false && messages.length > 0} diff --git a/src/lib/components/chat/MessageInput/Suggestions.svelte b/src/lib/components/chat/MessageInput/Suggestions.svelte index 20ffb211f..6bd1876b5 100644 --- a/src/lib/components/chat/MessageInput/Suggestions.svelte +++ b/src/lib/components/chat/MessageInput/Suggestions.svelte @@ -1,122 +1,43 @@ -
-
- +
+ {#if prompt.title} +
{prompt.title[0]}
+
{prompt.title[1]}
+ {:else} +
{prompt.content}
+ {/if} +
-
-
- - - -
- - - - - + {/each}
diff --git a/src/lib/components/chat/Messages.svelte b/src/lib/components/chat/Messages.svelte index cc27bdeee..9e7fd71ad 100644 --- a/src/lib/components/chat/Messages.svelte +++ b/src/lib/components/chat/Messages.svelte @@ -7,7 +7,7 @@ import auto_render from 'katex/dist/contrib/auto-render.mjs'; import 'katex/dist/katex.min.css'; - import { config, db, settings, user } from '$lib/stores'; + import { config, db, modelfiles, settings, user } from '$lib/stores'; import { tick } from 'svelte'; import toast from 'svelte-french-toast'; @@ -16,9 +16,12 @@ export let regenerateResponse: Function; export let autoScroll; + export let selectedModels; export let history = {}; export let messages = []; + export let selectedModelfile = null; + $: if (messages && messages.length > 0 && (messages.at(-1).done ?? false)) { (async () => { await tick(); @@ -306,10 +309,18 @@ {#if messages.length == 0}
- + {#if selectedModelfile && selectedModelfile.imageUrl} + + {:else} + + {/if}
-
- How can I help you today? +
+ {#if selectedModelfile} + {selectedModelfile.desc} + {:else} + How can I help you today? + {/if}
{:else} @@ -332,6 +343,12 @@ alt="User profile" /> {/if} + {:else if selectedModelfile} + Ollama profile {:else}
-
+
{#if message.role === 'user'} You + {:else if selectedModelfile} + {selectedModelfile.title} {:else} Ollama {message.model ? ` ${message.model}` : ''} + export let options = { + // Advanced + seed: 0, + stop: '', + temperature: '', + repeat_penalty: '', + repeat_last_n: '', + mirostat: '', + mirostat_eta: '', + mirostat_tau: '', + top_k: '', + top_p: '', + tfs_z: '', + num_ctx: '' + }; + + +
+
+
+
Seed
+
+ +
+
+
+ +
+
+
Stop Sequence
+
+ +
+
+
+ +
+
+
Temperature
+ + +
+ + {#if options.temperature !== ''} +
+
+ +
+
+ +
+
+ {/if} +
+ +
+
+
Mirostat
+ + +
+ + {#if options.mirostat !== ''} +
+
+ +
+
+ +
+
+ {/if} +
+ +
+
+
Mirostat Eta
+ + +
+ + {#if options.mirostat_eta !== ''} +
+
+ +
+
+ +
+
+ {/if} +
+ +
+
+
Mirostat Tau
+ + +
+ + {#if options.mirostat_tau !== ''} +
+
+ +
+
+ +
+
+ {/if} +
+ +
+
+
Top K
+ + +
+ + {#if options.top_k !== ''} +
+
+ +
+
+ +
+
+ {/if} +
+ +
+
+
Top P
+ + +
+ + {#if options.top_p !== ''} +
+
+ +
+
+ +
+
+ {/if} +
+ +
+
+
Repeat Penalty
+ + +
+ + {#if options.repeat_penalty !== ''} +
+
+ +
+
+ +
+
+ {/if} +
+ +
+
+
Repeat Last N
+ + +
+ + {#if options.repeat_last_n !== ''} +
+
+ +
+
+ +
+
+ {/if} +
+ +
+
+
Tfs Z
+ + +
+ + {#if options.tfs_z !== ''} +
+
+ +
+
+ +
+
+ {/if} +
+ +
+
+
Context Length
+ + +
+ + {#if options.num_ctx !== ''} +
+
+ +
+
+ +
+
+ {/if} +
+
diff --git a/src/lib/components/chat/SettingsModal.svelte b/src/lib/components/chat/SettingsModal.svelte index 31da70fea..a0d538aa4 100644 --- a/src/lib/components/chat/SettingsModal.svelte +++ b/src/lib/components/chat/SettingsModal.svelte @@ -6,6 +6,7 @@ import { onMount } from 'svelte'; import { config, models, settings, user } from '$lib/stores'; import { splitStream, getGravatarURL } from '$lib/utils'; + import Advanced from './Settings/Advanced.svelte'; export let show = false; @@ -25,12 +26,21 @@ // Advanced let requestFormat = ''; - let seed = 0; - let temperature = ''; - let repeat_penalty = ''; - let top_k = ''; - let top_p = ''; - let num_ctx = ''; + let options = { + // Advanced + seed: 0, + temperature: '', + repeat_penalty: '', + repeat_last_n: '', + mirostat: '', + mirostat_eta: '', + mirostat_tau: '', + top_k: '', + top_p: '', + stop: '', + tfs_z: '', + num_ctx: '' + }; // Models let modelTag = ''; @@ -218,28 +228,6 @@ models.set(await getModels()); }; - $: if (show) { - let settings = JSON.parse(localStorage.getItem('settings') ?? '{}'); - console.log(settings); - - theme = localStorage.theme ?? 'dark'; - API_BASE_URL = settings.API_BASE_URL ?? OLLAMA_API_BASE_URL; - system = settings.system ?? ''; - - requestFormat = settings.requestFormat ?? ''; - seed = settings.seed ?? 0; - temperature = settings.temperature ?? ''; - repeat_penalty = settings.repeat_penalty ?? ''; - top_k = settings.top_k ?? ''; - top_p = settings.top_p ?? ''; - num_ctx = settings.num_ctx ?? ''; - - titleAutoGenerate = settings.titleAutoGenerate ?? true; - speechAutoSend = settings.speechAutoSend ?? false; - gravatarEmail = settings.gravatarEmail ?? ''; - OPENAI_API_KEY = settings.OPENAI_API_KEY ?? ''; - } - const getModels = async (url = '', type = 'all') => { let models = []; const res = await fetch(`${url ? url : $settings?.API_BASE_URL ?? OLLAMA_API_BASE_URL}/tags`, { @@ -306,6 +294,26 @@ onMount(() => { let settings = JSON.parse(localStorage.getItem('settings') ?? '{}'); + console.log(settings); + + theme = localStorage.theme ?? 'dark'; + API_BASE_URL = settings.API_BASE_URL ?? OLLAMA_API_BASE_URL; + system = settings.system ?? ''; + + requestFormat = settings.requestFormat ?? ''; + + options.seed = settings.seed ?? 0; + options.temperature = settings.temperature ?? ''; + options.repeat_penalty = settings.repeat_penalty ?? ''; + options.top_k = settings.top_k ?? ''; + options.top_p = settings.top_p ?? ''; + options.num_ctx = settings.num_ctx ?? ''; + options = { ...options, ...settings.options }; + + titleAutoGenerate = settings.titleAutoGenerate ?? true; + speechAutoSend = settings.speechAutoSend ?? false; + gravatarEmail = settings.gravatarEmail ?? ''; + OPENAI_API_KEY = settings.OPENAI_API_KEY ?? ''; authEnabled = settings.authHeader !== undefined ? true : false; if (authEnabled) { @@ -497,7 +505,7 @@
About
-
+
{#if selectedTab === 'general'}
@@ -612,234 +620,11 @@
{:else if selectedTab === 'advanced'} -
-
-
-
-
Seed
-
- -
-
-
- -
-
-
Temperature
- - -
- - {#if temperature !== ''} -
-
- -
-
- -
-
- {/if} -
- -
-
-
Repeat Penalty
- - -
- - {#if repeat_penalty !== ''} -
-
- -
-
- -
-
- {/if} -
- -
-
-
Top K
- - -
- - {#if top_k !== ''} -
-
- -
-
- -
-
- {/if} -
- -
-
-
Top P
- - -
- - {#if top_p !== ''} -
-
- -
-
- -
-
- {/if} -
- -
-
-
Context Length
- - -
- - {#if num_ctx !== ''} -
-
- -
-
- -
-
- {/if} -
+
+
+
Parameters
+
@@ -871,17 +656,28 @@
+
-
+
{digest}
diff --git a/src/lib/components/layout/Sidebar.svelte b/src/lib/components/layout/Sidebar.svelte index 656d3f451..bb54dbc1a 100644 --- a/src/lib/components/layout/Sidebar.svelte +++ b/src/lib/components/layout/Sidebar.svelte @@ -24,7 +24,7 @@ let showDropdown = false; - let showDeleteHistoryConfirm = false; + let showDeleteHistoryConfirm = false; onMount(async () => { if (window.innerWidth > 1280) { @@ -121,11 +121,11 @@
- +
@@ -449,91 +449,92 @@
Export
- {#if showDeleteHistoryConfirm} -
-
- - - - Are you sure? -
- -
- - -
-
- {:else} - - {/if} + {#if showDeleteHistoryConfirm} +
+
+ + + + Are you sure? +
+ +
+ + +
+
+ {:else} + + {/if} {#if $user !== undefined}
- +
- +
diff --git a/src/routes/(app)/c/[id]/+page.svelte b/src/routes/(app)/c/[id]/+page.svelte index e6539e8d9..c8ab7882b 100644 --- a/src/routes/(app)/c/[id]/+page.svelte +++ b/src/routes/(app)/c/[id]/+page.svelte @@ -6,7 +6,7 @@ import { onMount, tick } from 'svelte'; import { convertMessagesToHistory, splitStream } from '$lib/utils'; import { goto } from '$app/navigation'; - import { config, user, settings, db, chats, chatId } from '$lib/stores'; + import { config, modelfiles, user, settings, db, chats, chatId } from '$lib/stores'; import MessageInput from '$lib/components/chat/MessageInput.svelte'; import Messages from '$lib/components/chat/Messages.svelte'; @@ -20,6 +20,12 @@ // let chatId = $page.params.id; let selectedModels = ['']; + let selectedModelfile = null; + $: selectedModelfile = + selectedModels.length === 1 && + $modelfiles.filter((modelfile) => modelfile.tagName === selectedModels[0]).length > 0 + ? $modelfiles.filter((modelfile) => modelfile.tagName === selectedModels[0])[0] + : null; let title = ''; let prompt = ''; @@ -161,7 +167,8 @@ repeat_penalty: $settings.repeat_penalty ?? undefined, top_k: $settings.top_k ?? undefined, top_p: $settings.top_p ?? undefined, - num_ctx: $settings.num_ctx ?? undefined + num_ctx: $settings.num_ctx ?? undefined, + ...($settings.options ?? {}) }, format: $settings.requestFormat ?? undefined, context: @@ -233,7 +240,8 @@ repeat_penalty: $settings.repeat_penalty ?? undefined, top_k: $settings.top_k ?? undefined, top_p: $settings.top_p ?? undefined, - num_ctx: $settings.num_ctx ?? undefined + num_ctx: $settings.num_ctx ?? undefined, + ...($settings.options ?? {}) }, messages: messages, history: history @@ -301,7 +309,7 @@ .map((message) => ({ role: message.role, content: message.content })), temperature: $settings.temperature ?? undefined, top_p: $settings.top_p ?? undefined, - num_ctx: $settings.num_ctx ?? undefined, + num_ctx: $settings.num_ctx ?? undefined, frequency_penalty: $settings.repeat_penalty ?? undefined }) }); @@ -362,7 +370,8 @@ repeat_penalty: $settings.repeat_penalty ?? undefined, top_k: $settings.top_k ?? undefined, top_p: $settings.top_p ?? undefined, - num_ctx: $settings.num_ctx ?? undefined + num_ctx: $settings.num_ctx ?? undefined, + ...($settings.options ?? {}) }, messages: messages, history: history @@ -424,7 +433,8 @@ repeat_penalty: $settings.repeat_penalty ?? undefined, top_k: $settings.top_k ?? undefined, top_p: $settings.top_p ?? undefined, - num_ctx: $settings.num_ctx ?? undefined + num_ctx: $settings.num_ctx ?? undefined, + ...($settings.options ?? {}) }, messages: messages, history: history @@ -517,10 +527,42 @@
- +
- +
{/if} diff --git a/src/routes/(app)/modelfiles/+page.svelte b/src/routes/(app)/modelfiles/+page.svelte new file mode 100644 index 000000000..ca46f393b --- /dev/null +++ b/src/routes/(app)/modelfiles/+page.svelte @@ -0,0 +1,159 @@ + + +
+
+
+
My Modelfiles
+ + +
+
+ + + +
+
+ +
+
Create a modelfile
+
Customize Ollama models for a specific purpose
+
+
+ + {#each $modelfiles as modelfile} +
+
+ +
+
+ modelfile profile +
+
+ +
+
{modelfile.title}
+
+ {modelfile.desc} +
+
+
+
+ + Edit + + +
+
+ {/each} + + +
+
+
diff --git a/src/routes/(app)/modelfiles/create/+page.svelte b/src/routes/(app)/modelfiles/create/+page.svelte new file mode 100644 index 000000000..989f34c00 --- /dev/null +++ b/src/routes/(app)/modelfiles/create/+page.svelte @@ -0,0 +1,685 @@ + + +
+
+
+ { + let reader = new FileReader(); + reader.onload = (event) => { + let originalImageUrl = `${event.target.result}`; + + const img = new Image(); + img.src = originalImageUrl; + + img.onload = function () { + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext('2d'); + + // Calculate the aspect ratio of the image + const aspectRatio = img.width / img.height; + + // Calculate the new width and height to fit within 100x100 + let newWidth, newHeight; + if (aspectRatio > 1) { + newWidth = 100 * aspectRatio; + newHeight = 100; + } else { + newWidth = 100; + newHeight = 100 / aspectRatio; + } + + // Set the canvas size + canvas.width = 100; + canvas.height = 100; + + // Calculate the position to center the image + const offsetX = (100 - newWidth) / 2; + const offsetY = (100 - newHeight) / 2; + + // Draw the image on the canvas + ctx.drawImage(img, offsetX, offsetY, newWidth, newHeight); + + // Get the base64 representation of the compressed image + const compressedSrc = canvas.toDataURL('image/jpeg'); + + // Display the compressed image + imageUrl = compressedSrc; + + inputFiles = null; + }; + }; + + if ( + inputFiles && + inputFiles.length > 0 && + ['image/gif', 'image/jpeg', 'image/png'].includes(inputFiles[0]['type']) + ) { + reader.readAsDataURL(inputFiles[0]); + } else { + console.log(`Unsupported File Type '${inputFiles[0]['type']}'.`); + inputFiles = null; + } + }} + /> + +
My Modelfiles
+ + +
+ +
{ + submitHandler(); + }} + > +
+
+ +
+
+ +
+
+
Name*
+ +
+ +
+
+ +
+
Model Tag Name*
+ +
+ +
+
+
+ +
+
Description*
+ +
+ +
+
+ +
+
+
Modelfile
+ + +
+ + + + {#if raw} +
+
Content*
+ +
+