From 8dbac0f7e3b4038e5f3f331bc2fad3d702ddfe57 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 21 Sep 2024 22:12:41 +0200 Subject: [PATCH 01/47] enh: show model hash and modified ts --- src/lib/components/workspace/Models.svelte | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/lib/components/workspace/Models.svelte b/src/lib/components/workspace/Models.svelte index 7c2b80fd4..4541b1cc9 100644 --- a/src/lib/components/workspace/Models.svelte +++ b/src/lib/components/workspace/Models.svelte @@ -1,4 +1,6 @@
-
- {data?.user?.name ?? 'User'} +
+
+ {data?.user?.name ?? 'User'} +
{#if data?.message?.error} @@ -43,8 +46,24 @@ />
-
- {data?.model?.name ?? data?.message?.model ?? 'Assistant'} +
+
+ {data?.model?.name ?? data?.message?.model ?? 'Assistant'} +
+ +
{#if data?.message?.error} From c292fd89f9f6164e450818d696ca20f6eef26b6d Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 22 Sep 2024 02:55:45 +0200 Subject: [PATCH 07/47] refac --- backend/open_webui/apps/socket/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/open_webui/apps/socket/main.py b/backend/open_webui/apps/socket/main.py index e84ce18bb..7883b7d8b 100644 --- a/backend/open_webui/apps/socket/main.py +++ b/backend/open_webui/apps/socket/main.py @@ -69,7 +69,6 @@ TIMEOUT_DURATION = 3 async def periodic_usage_pool_cleanup(): while True: now = int(time.time()) - log.debug(f"Cleaning up usage pool: {now}") for model_id, connections in list(USAGE_POOL.items()): # Creating a list of sids to remove if they have timed out expired_sids = [ @@ -82,6 +81,7 @@ async def periodic_usage_pool_cleanup(): del connections[sid] if not connections: + log.debug(f"Cleaning up model {model_id} from usage pool") del USAGE_POOL[model_id] else: USAGE_POOL[model_id] = connections From 620e629edc32b0c6d8aba247de872279907cebdb Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 22 Sep 2024 02:57:38 +0200 Subject: [PATCH 08/47] refac --- src/lib/components/chat/Overview/Node.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/chat/Overview/Node.svelte b/src/lib/components/chat/Overview/Node.svelte index a3cf5ebd8..25387c050 100644 --- a/src/lib/components/chat/Overview/Node.svelte +++ b/src/lib/components/chat/Overview/Node.svelte @@ -47,7 +47,7 @@
-
+
{data?.model?.name ?? data?.message?.model ?? 'Assistant'}
From d6d6098378843c9e89213eb3b5a2521b32fced71 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 22 Sep 2024 02:57:51 +0200 Subject: [PATCH 09/47] refac --- src/lib/components/chat/Overview/Node.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/chat/Overview/Node.svelte b/src/lib/components/chat/Overview/Node.svelte index 25387c050..e00f53653 100644 --- a/src/lib/components/chat/Overview/Node.svelte +++ b/src/lib/components/chat/Overview/Node.svelte @@ -26,7 +26,7 @@ />
-
+
{data?.user?.name ?? 'User'}
From 96ef15362a536be5b1138d89c9f095c766a8fdbf Mon Sep 17 00:00:00 2001 From: James Clarke Date: Sun, 22 Sep 2024 05:11:59 +0100 Subject: [PATCH 10/47] Increased max_tokens (num_predict) to 131072, fixes #5600 --- .../components/chat/Settings/Advanced/AdvancedParams.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte b/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte index d1b566b63..dd55b6a06 100644 --- a/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte +++ b/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte @@ -734,7 +734,7 @@ id="steps-range" type="range" min="-2" - max="16000" + max="131072" step="1" bind:value={params.max_tokens} class="w-full h-2 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" @@ -746,7 +746,7 @@ type="number" class=" bg-transparent text-center w-14" min="-2" - max="16000" + max="131072" step="1" />
From d53062a9b0ed7332dc79ac42a8a94fe0e037b6df Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sun, 22 Sep 2024 00:02:07 +0200 Subject: [PATCH 11/47] Add more variables to prompts --- .../chat/MessageInput/Commands/Prompts.svelte | 50 +++++++++++++++++-- src/lib/utils/index.ts | 30 ++++++++++- 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/src/lib/components/chat/MessageInput/Commands/Prompts.svelte b/src/lib/components/chat/MessageInput/Commands/Prompts.svelte index 9fd48c749..8e8052575 100644 --- a/src/lib/components/chat/MessageInput/Commands/Prompts.svelte +++ b/src/lib/components/chat/MessageInput/Commands/Prompts.svelte @@ -1,6 +1,14 @@
- {#if messages.length == 0} + {#if Object.keys(history?.messages ?? {}).length == 0} { @@ -327,116 +315,9 @@ {:else}
{#key chatId} - {#each messages as message, messageIdx (message.id)} -
-
- {#if message.role === 'user'} - deleteMessageHandler(message.id)} - {user} - {readOnly} - {message} - isFirstMessage={messageIdx === 0} - siblings={message.parentId !== null - ? (history.messages[message.parentId]?.childrenIds ?? []) - : (Object.values(history.messages) - .filter((message) => message.parentId === null) - .map((message) => message.id) ?? [])} - {confirmEditMessage} - {showPreviousMessage} - {showNextMessage} - copyToClipboard={copyToClipboardWithToast} - /> - {:else if (history.messages[message.parentId]?.models?.length ?? 1) === 1} - {#key message.id} - { - console.log('action', e); - if (typeof e.detail === 'string') { - await chatActionHandler(chatId, e.detail, message.model, message.id); - } else { - const { id, event } = e.detail; - await chatActionHandler(chatId, id, message.model, message.id, event); - } - }} - on:save={async (e) => { - console.log('save', e); - - const message = e.detail; - history.messages[message.id] = message; - await updateChatById(localStorage.token, chatId, { - messages: messages, - history: history - }); - }} - /> - {/key} - {:else} - {#key message.parentId} - { - console.log('action', e); - if (typeof e.detail === 'string') { - await chatActionHandler(chatId, e.detail, message.model, message.id); - } else { - const { id, event } = e.detail; - await chatActionHandler(chatId, id, message.model, message.id, event); - } - }} - on:change={async () => { - await updateChatById(localStorage.token, chatId, { - messages: messages, - history: history - }); - - if (autoScroll) { - const element = document.getElementById('messages-container'); - autoScroll = - element.scrollHeight - element.scrollTop <= element.clientHeight + 50; - setTimeout(() => { - scrollToBottom(); - }, 100); - } - }} - /> - {/key} - {/if} -
-
- {/each} - + {JSON.stringify(history)} + +
{#if bottomPadding}
{/if} diff --git a/src/lib/components/chat/Messages/Message.svelte b/src/lib/components/chat/Messages/Message.svelte new file mode 100644 index 000000000..1629a765e --- /dev/null +++ b/src/lib/components/chat/Messages/Message.svelte @@ -0,0 +1,156 @@ + + +
+
+ {#if history.messages[messageId].role === 'user'} + {@const message = history.messages[messageId]} + message.parentId === null) + .map((message) => message.id) ?? [])} + {confirmEditMessage} + {showPreviousMessage} + {showNextMessage} + copyToClipboard={copyToClipboardWithToast} + isFirstMessage={messageIdx === 0} + on:delete={() => deleteMessage(message.id)} + {readOnly} + /> + {:else if (history.messages[message.parentId]?.models?.length ?? 1) === 1} + { + console.log('action', e); + if (typeof e.detail === 'string') { + await chatActionHandler(chatId, e.detail, message.model, message.id); + } else { + const { id, event } = e.detail; + await chatActionHandler(chatId, id, message.model, message.id, event); + } + }} + on:save={async (e) => { + console.log('save', e); + + const message = e.detail; + if (message) { + history.messages[message.id] = message; + await updateChatById(localStorage.token, chatId, { + history: history + }); + } else { + await updateChatById(localStorage.token, chatId, { + history: history + }); + } + }} + /> + {:else} + { + console.log('action', e); + if (typeof e.detail === 'string') { + await chatActionHandler(chatId, e.detail, message.model, message.id); + } else { + const { id, event } = e.detail; + await chatActionHandler(chatId, id, message.model, message.id, event); + } + }} + on:change={async () => { + await updateChatById(localStorage.token, chatId, { + history: history + }); + + if (autoScroll) { + const element = document.getElementById('messages-container'); + autoScroll = element.scrollHeight - element.scrollTop <= element.clientHeight + 50; + setTimeout(() => { + scrollToBottom(); + }, 100); + } + }} + /> + {/if} +
+
diff --git a/src/lib/components/chat/Messages/MultiResponseMessages.svelte b/src/lib/components/chat/Messages/MultiResponseMessages.svelte index 4a845dbb9..c35ab9412 100644 --- a/src/lib/components/chat/Messages/MultiResponseMessages.svelte +++ b/src/lib/components/chat/Messages/MultiResponseMessages.svelte @@ -22,7 +22,6 @@ export let chatId; export let history; - export let messages = []; export let messageIdx; export let parentMessage; @@ -46,7 +45,9 @@ let groupedMessages = {}; let groupedMessagesIdx = {}; - $: if (parentMessage) { + $: if (history.messages) { + console.log('history.messages', history.messages); + initHandler(); } @@ -87,6 +88,7 @@ }; const initHandler = async () => { + console.log('multiresponse:initHandler'); await tick(); currentMessageId = messages[messageIdx].id; @@ -146,78 +148,76 @@ class="flex snap-x snap-mandatory overflow-x-auto scrollbar-hidden" id="responses-container-{chatId}-{parentMessage.id}" > - {#key currentMessageId} - {#each Object.keys(groupedMessages) as modelIdx} - {#if groupedMessagesIdx[modelIdx] !== undefined && groupedMessages[modelIdx].messages.length > 0} - - - {@const message = groupedMessages[modelIdx].messages[groupedMessagesIdx[modelIdx]]} + {#each Object.keys(groupedMessages) as modelIdx} + {#if groupedMessagesIdx[modelIdx] !== undefined && groupedMessages[modelIdx].messages.length > 0} + + + {@const message = groupedMessages[modelIdx].messages[groupedMessagesIdx[modelIdx]]} -
{ - if (currentMessageId != message.id) { - currentMessageId = message.id; - let messageId = message.id; - console.log(messageId); - // - let messageChildrenIds = history.messages[messageId].childrenIds; - while (messageChildrenIds.length !== 0) { - messageId = messageChildrenIds.at(-1); - messageChildrenIds = history.messages[messageId].childrenIds; - } - history.currentId = messageId; - dispatch('change'); +
{ + if (currentMessageId != message.id) { + currentMessageId = message.id; + let messageId = message.id; + console.log(messageId); + // + let messageChildrenIds = history.messages[messageId].childrenIds; + while (messageChildrenIds.length !== 0) { + messageId = messageChildrenIds.at(-1); + messageChildrenIds = history.messages[messageId].childrenIds; } - }} - > - {#key history.currentId} - {#if message} - m.id)} - isLastMessage={true} - {updateChatMessages} - {saveNewResponseMessage} - {confirmEditResponseMessage} - showPreviousMessage={() => showPreviousMessage(modelIdx)} - showNextMessage={() => showNextMessage(modelIdx)} - {readOnly} - {rateMessage} - {copyToClipboard} - {continueGeneration} - regenerateResponse={async (message) => { - regenerateResponse(message); - await tick(); - groupedMessagesIdx[modelIdx] = groupedMessages[modelIdx].messages.length - 1; - }} - on:action={async (e) => { - dispatch('action', e.detail); - }} - on:save={async (e) => { - console.log('save', e); + history.currentId = messageId; + dispatch('change'); + } + }} + > + {#key history.currentId} + {#if message} + m.id)} + isLastMessage={true} + {updateChatMessages} + {saveNewResponseMessage} + {confirmEditResponseMessage} + showPreviousMessage={() => showPreviousMessage(modelIdx)} + showNextMessage={() => showNextMessage(modelIdx)} + {readOnly} + {rateMessage} + {copyToClipboard} + {continueGeneration} + regenerateResponse={async (message) => { + regenerateResponse(message); + await tick(); + groupedMessagesIdx[modelIdx] = groupedMessages[modelIdx].messages.length - 1; + }} + on:action={async (e) => { + dispatch('action', e.detail); + }} + on:save={async (e) => { + console.log('save', e); - const message = e.detail; - history.messages[message.id] = message; - await updateChatById(localStorage.token, chatId, { - messages: messages, - history: history - }); - }} - /> - {/if} - {/key} -
- {/if} - {/each} - {/key} + const message = e.detail; + history.messages[message.id] = message; + await updateChatById(localStorage.token, chatId, { + messages: messages, + history: history + }); + }} + /> + {/if} + {/key} +
+ {/if} + {/each}
{#if !readOnly && isLastMessage} From 5978e7c9a6bedf8f888cbdec672f017b68fa44e6 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Mon, 23 Sep 2024 01:36:46 +0200 Subject: [PATCH 21/47] refac: wip --- src/lib/components/chat/Chat.svelte | 102 +++++----- src/lib/components/chat/Messages.svelte | 186 +++++++++--------- .../components/chat/Messages/Message.svelte | 87 ++++---- .../Messages/MultiResponseMessages.svelte | 4 +- .../chat/Messages/ResponseMessage.svelte | 32 +-- .../chat/Messages/UserMessage.svelte | 35 ++-- src/routes/s/[id]/+page.svelte | 2 +- 7 files changed, 244 insertions(+), 204 deletions(-) diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index f9e23ca2f..25928ddd7 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -1520,8 +1520,8 @@ } }; - const continueGeneration = async () => { - console.log('continueGeneration'); + const continueResponse = async () => { + console.log('continueResponse'); const _chatId = JSON.parse(JSON.stringify($chatId)); if (history.currentId && history.messages[history.currentId].done == true) { @@ -1552,6 +1552,53 @@ } }; + const mergeResponses = async (messageId, responses, _chatId) => { + console.log('mergeResponses', messageId, responses); + const message = history.messages[messageId]; + const mergedResponse = { + status: true, + content: '' + }; + message.merged = mergedResponse; + history.messages[messageId] = message; + + try { + const [res, controller] = await generateMoACompletion( + localStorage.token, + message.model, + history.messages[message.parentId].content, + responses + ); + + if (res && res.ok && res.body) { + const textStream = await createOpenAITextStream(res.body, $settings.splitLargeChunks); + for await (const update of textStream) { + const { value, done, citations, error, usage } = update; + if (error || done) { + break; + } + + if (mergedResponse.content == '' && value == '\n') { + continue; + } else { + mergedResponse.content += value; + history.messages[messageId] = message; + } + + if (autoScroll) { + scrollToBottom(); + } + } + + await saveChatHandler(_chatId); + } else { + console.error(res); + } + } catch (e) { + console.error(e); + } + }; + const generateChatTitle = async (userPrompt) => { if ($settings?.title?.auto ?? true) { const title = await generateTitle( @@ -1684,52 +1731,6 @@ } } }; - const mergeResponses = async (messageId, responses, _chatId) => { - console.log('mergeResponses', messageId, responses); - const message = history.messages[messageId]; - const mergedResponse = { - status: true, - content: '' - }; - message.merged = mergedResponse; - history.messages[messageId] = message; - - try { - const [res, controller] = await generateMoACompletion( - localStorage.token, - message.model, - history.messages[message.parentId].content, - responses - ); - - if (res && res.ok && res.body) { - const textStream = await createOpenAITextStream(res.body, $settings.splitLargeChunks); - for await (const update of textStream) { - const { value, done, citations, error, usage } = update; - if (error || done) { - break; - } - - if (mergedResponse.content == '' && value == '\n') { - continue; - } else { - mergedResponse.content += value; - history.messages[messageId] = message; - } - - if (autoScroll) { - scrollToBottom(); - } - } - - await saveChatHandler(_chatId); - } else { - console.error(res); - } - } catch (e) { - console.error(e); - } - }; @@ -1827,13 +1828,12 @@ bind:autoScroll bind:prompt {selectedModels} - {processing} {sendPrompt} - {continueGeneration} + {showMessage} + {continueResponse} {regenerateResponse} {mergeResponses} {chatActionHandler} - {showMessage} bottomPadding={files.length > 0} />
diff --git a/src/lib/components/chat/Messages.svelte b/src/lib/components/chat/Messages.svelte index 7ea3a3d69..596458578 100644 --- a/src/lib/components/chat/Messages.svelte +++ b/src/lib/components/chat/Messages.svelte @@ -15,7 +15,7 @@ export let chatId = ''; export let readOnly = false; export let sendPrompt: Function; - export let continueGeneration: Function; + export let continueResponse: Function; export let regenerateResponse: Function; export let mergeResponses: Function; export let chatActionHandler: Function; @@ -23,7 +23,6 @@ export let user = $_user; export let prompt; - export let processing = ''; export let bottomPadding = false; export let autoScroll; export let history = {}; @@ -43,7 +42,7 @@ element.scrollTop = element.scrollHeight; }; - const updateChatMessages = async () => { + const updateChatHistory = async () => { await tick(); await updateChatById(localStorage.token, chatId, { history: history @@ -53,87 +52,6 @@ await chats.set(await getChatList(localStorage.token, $currentChatPage)); }; - const confirmEditMessage = async (messageId, content, submit = true) => { - if (submit) { - let userPrompt = content; - let userMessageId = uuidv4(); - - let userMessage = { - id: userMessageId, - parentId: history.messages[messageId].parentId, - childrenIds: [], - role: 'user', - content: userPrompt, - ...(history.messages[messageId].files && { files: history.messages[messageId].files }), - models: selectedModels - }; - - let messageParentId = history.messages[messageId].parentId; - - if (messageParentId !== null) { - history.messages[messageParentId].childrenIds = [ - ...history.messages[messageParentId].childrenIds, - userMessageId - ]; - } - - history.messages[userMessageId] = userMessage; - history.currentId = userMessageId; - - await tick(); - await sendPrompt(userPrompt, userMessageId); - } else { - history.messages[messageId].content = content; - await tick(); - await updateChatById(localStorage.token, chatId, { - history: history - }); - } - }; - - const confirmEditResponseMessage = async (messageId, content) => { - history.messages[messageId].originalContent = history.messages[messageId].content; - history.messages[messageId].content = content; - - await updateChatMessages(); - }; - - const saveNewResponseMessage = async (message, content) => { - const responseMessageId = uuidv4(); - const parentId = message.parentId; - - const responseMessage = { - ...message, - id: responseMessageId, - parentId: parentId, - childrenIds: [], - content: content, - timestamp: Math.floor(Date.now() / 1000) // Unix epoch - }; - - history.messages[responseMessageId] = responseMessage; - history.currentId = responseMessageId; - - // Append messageId to childrenIds of parent message - if (parentId !== null) { - history.messages[parentId].childrenIds = [ - ...history.messages[parentId].childrenIds, - responseMessageId - ]; - } - - await updateChatMessages(); - }; - - const rateMessage = async (messageId, rating) => { - history.messages[messageId].annotation = { - ...history.messages[messageId].annotation, - rating: rating - }; - - await updateChatMessages(); - }; - const showPreviousMessage = async (message) => { if (message.parentId !== null) { let messageId = @@ -232,6 +150,87 @@ } }; + const rateMessage = async (messageId, rating) => { + history.messages[messageId].annotation = { + ...history.messages[messageId].annotation, + rating: rating + }; + + await updateChatHistory(); + }; + + const editMessage = async (messageId, content, submit = true) => { + if (history.messages[messageId].role === 'user') { + if (submit) { + // New user message + let userPrompt = content; + let userMessageId = uuidv4(); + + let userMessage = { + id: userMessageId, + parentId: history.messages[messageId].parentId, + childrenIds: [], + role: 'user', + content: userPrompt, + ...(history.messages[messageId].files && { files: history.messages[messageId].files }), + models: selectedModels + }; + + let messageParentId = history.messages[messageId].parentId; + + if (messageParentId !== null) { + history.messages[messageParentId].childrenIds = [ + ...history.messages[messageParentId].childrenIds, + userMessageId + ]; + } + + history.messages[userMessageId] = userMessage; + history.currentId = userMessageId; + + await tick(); + await sendPrompt(userPrompt, userMessageId); + } else { + // Edit user message + history.messages[messageId].content = content; + await updateChatHistory(); + } + } else { + if (submit) { + // New response message + const responseMessageId = uuidv4(); + const parentId = message.parentId; + + const responseMessage = { + ...message, + id: responseMessageId, + parentId: parentId, + childrenIds: [], + content: content, + timestamp: Math.floor(Date.now() / 1000) // Unix epoch + }; + + history.messages[responseMessageId] = responseMessage; + history.currentId = responseMessageId; + + // Append messageId to childrenIds of parent message + if (parentId !== null) { + history.messages[parentId].childrenIds = [ + ...history.messages[parentId].childrenIds, + responseMessageId + ]; + } + + await updateChatHistory(); + } else { + // Edit response message + history.messages[messageId].originalContent = history.messages[messageId].content; + history.messages[messageId].content = content; + await updateChatHistory(); + } + } + }; + const deleteMessage = async (messageId) => { const messageToDelete = history.messages[messageId]; const parentMessageId = messageToDelete.parentId; @@ -267,9 +266,7 @@ showMessage({ id: parentMessageId }); // Update the chat - await updateChatById(localStorage.token, chatId, { - history: history - }); + await updateChatHistory(); }; @@ -315,8 +312,19 @@ {:else}
{#key chatId} - {JSON.stringify(history)} - + +
+ +
{#if bottomPadding}
diff --git a/src/lib/components/chat/Messages/Message.svelte b/src/lib/components/chat/Messages/Message.svelte index 1629a765e..9a328e0d7 100644 --- a/src/lib/components/chat/Messages/Message.svelte +++ b/src/lib/components/chat/Messages/Message.svelte @@ -10,6 +10,10 @@ import MultiResponseMessages from './MultiResponseMessages.svelte'; import ResponseMessage from './ResponseMessage.svelte'; import UserMessage from './UserMessage.svelte'; + import { updateChatById } from '$lib/apis/chats'; + + // h here refers to the height of the message graph + export let h; export let chatId; @@ -21,19 +25,15 @@ export let scrollToBottom; export let chatActionHandler; - export let confirmEditMessage; - export let confirmEditResponseMessage; - export let showPreviousMessage; export let showNextMessage; - export let rateMessage; + export let editMessage; export let deleteMessage; - - export let saveNewResponseMessage; + export let rateMessage; export let regenerateResponse; - export let continueGeneration; + export let continueResponse; // MultiResponseMessages export let mergeResponses; @@ -48,44 +48,39 @@ }; -
-
- {#if history.messages[messageId].role === 'user'} - {@const message = history.messages[messageId]} +
+ {#if history.messages[messageId]} + {@const message = history.messages[messageId]} + {#if message.role === 'user'} message.parentId === null) .map((message) => message.id) ?? [])} - {confirmEditMessage} {showPreviousMessage} {showNextMessage} - copyToClipboard={copyToClipboardWithToast} - isFirstMessage={messageIdx === 0} + {editMessage} on:delete={() => deleteMessage(message.id)} {readOnly} /> {:else if (history.messages[message.parentId]?.models?.length ?? 1) === 1} { console.log('action', e); @@ -96,6 +91,10 @@ await chatActionHandler(chatId, id, message.model, message.id, event); } }} + on:update={async (e) => { + console.log('update', e); + // call updateChatHistory + }} on:save={async (e) => { console.log('save', e); @@ -111,6 +110,7 @@ }); } }} + {readOnly} /> {:else} { console.log('action', e); if (typeof e.detail === 'string') { @@ -152,5 +150,26 @@ }} /> {/if} -
+ {/if}
+ +{#if history.messages[messageId]?.parentId !== null} + +{/if} diff --git a/src/lib/components/chat/Messages/MultiResponseMessages.svelte b/src/lib/components/chat/Messages/MultiResponseMessages.svelte index c35ab9412..6b116a396 100644 --- a/src/lib/components/chat/Messages/MultiResponseMessages.svelte +++ b/src/lib/components/chat/Messages/MultiResponseMessages.svelte @@ -34,7 +34,7 @@ export let rateMessage: Function; export let copyToClipboard: Function; - export let continueGeneration: Function; + export let continueResponse: Function; export let mergeResponses: Function; export let regenerateResponse: Function; export let saveNewResponseMessage: Function; @@ -193,7 +193,7 @@ {readOnly} {rateMessage} {copyToClipboard} - {continueGeneration} + {continueResponse} regenerateResponse={async (message) => { regenerateResponse(message); await tick(); diff --git a/src/lib/components/chat/Messages/ResponseMessage.svelte b/src/lib/components/chat/Messages/ResponseMessage.svelte index af892bcfa..f0a0660e2 100644 --- a/src/lib/components/chat/Messages/ResponseMessage.svelte +++ b/src/lib/components/chat/Messages/ResponseMessage.svelte @@ -13,6 +13,7 @@ import { synthesizeOpenAISpeech } from '$lib/apis/audio'; import { imageGenerations } from '$lib/apis/images'; import { + copyToClipboard as _copyToClipboard, approximateToHumanReadable, extractParagraphsForAudio, extractSentencesForAudio, @@ -83,16 +84,15 @@ export let readOnly = false; - export let updateChatMessages: Function; - export let confirmEditResponseMessage: Function; export let saveNewResponseMessage: Function = () => {}; export let showPreviousMessage: Function; export let showNextMessage: Function; + + export let editMessage: Function; export let rateMessage: Function; - export let copyToClipboard: Function; - export let continueGeneration: Function; + export let continueResponse: Function; export let regenerateResponse: Function; let model = null; @@ -111,6 +111,13 @@ let showRateComment = false; + const copyToClipboard = async (text) => { + const res = await _copyToClipboard(text); + if (res) { + toast.success($i18n.t('Copying to clipboard was successful!')); + } + }; + const playAudio = (idx: number) => { return new Promise((res) => { speakingIdx = idx; @@ -260,11 +267,7 @@ }; const editMessageConfirmHandler = async () => { - if (editedContent === '') { - editedContent = ' '; - } - - confirmEditResponseMessage(message.id, editedContent); + editMessage(message.id, editedContent ? editedContent : '', false); edit = false; editedContent = ''; @@ -272,8 +275,8 @@ await tick(); }; - const saveNewMessageHandler = async () => { - saveNewResponseMessage(message, editedContent); + const saveAsCopyHandler = async () => { + editMessage(message.id, editedContent ? editedContent : ''); edit = false; editedContent = ''; @@ -424,7 +427,7 @@ id="save-new-message-button" class=" px-4 py-2 bg-gray-50 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700 border dark:border-gray-700 text-gray-700 dark:text-gray-200 transition rounded-3xl" on:click={() => { - saveNewMessageHandler(); + saveAsCopyHandler(); }} > {$i18n.t('Save As Copy')} @@ -909,7 +912,7 @@ ? 'visible' : 'invisible group-hover:visible'} p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg dark:hover:text-white hover:text-black transition regenerate-response-button" on:click={() => { - continueGeneration(); + continueResponse(); (model?.actions ?? []) .filter((action) => action?.__webui__ ?? false) @@ -1028,8 +1031,7 @@ bind:show={showRateComment} bind:message on:submit={(e) => { - updateChatMessages(); - + dispatch('update'); (model?.actions ?? []) .filter((action) => action?.__webui__ ?? false) .forEach((action) => { diff --git a/src/lib/components/chat/Messages/UserMessage.svelte b/src/lib/components/chat/Messages/UserMessage.svelte index 351e3c0da..532f85de2 100644 --- a/src/lib/components/chat/Messages/UserMessage.svelte +++ b/src/lib/components/chat/Messages/UserMessage.svelte @@ -1,18 +1,20 @@ -{#each tokens as token, tokenIdx} +{#each tokens as token, tokenIdx (tokenIdx)} {#if token.type === 'hr'}
{:else if token.type === 'heading'} diff --git a/src/lib/components/chat/Messages/Message.svelte b/src/lib/components/chat/Messages/Message.svelte index 9a328e0d7..d60e17cc4 100644 --- a/src/lib/components/chat/Messages/Message.svelte +++ b/src/lib/components/chat/Messages/Message.svelte @@ -12,10 +12,8 @@ import UserMessage from './UserMessage.svelte'; import { updateChatById } from '$lib/apis/chats'; - // h here refers to the height of the message graph - export let h; - export let chatId; + export let idx = 0; export let history; export let messageId; @@ -40,12 +38,23 @@ export let readOnly = false; + let message = JSON.parse(JSON.stringify(history.messages[messageId])); + $: if (history.messages) { + if (JSON.stringify(message) !== JSON.stringify(history.messages[messageId])) { + message = JSON.parse(JSON.stringify(history.messages[messageId])); + } + } + const copyToClipboardWithToast = async (text) => { const res = await copyToClipboard(text); if (res) { toast.success($i18n.t('Copying to clipboard was successful!')); } }; + + onMount(() => { + console.log('message', idx); + });
- {#if history.messages[messageId]} - {@const message = history.messages[messageId]} + {#if message} {#if message.role === 'user'} - -{#if history.messages[messageId]?.parentId !== null} - -{/if} diff --git a/src/lib/components/chat/Messages/ResponseMessage.svelte b/src/lib/components/chat/Messages/ResponseMessage.svelte index f0a0660e2..c62c20b6b 100644 --- a/src/lib/components/chat/Messages/ResponseMessage.svelte +++ b/src/lib/components/chat/Messages/ResponseMessage.svelte @@ -316,6 +316,8 @@ } onMount(async () => { + console.log('ResponseMessage mounted'); + await tick(); }); diff --git a/src/lib/components/chat/Messages/UserMessage.svelte b/src/lib/components/chat/Messages/UserMessage.svelte index 532f85de2..3f0fd7be9 100644 --- a/src/lib/components/chat/Messages/UserMessage.svelte +++ b/src/lib/components/chat/Messages/UserMessage.svelte @@ -1,7 +1,7 @@
From ac277e8e9ed4a47c019096e74a187e839aa3891b Mon Sep 17 00:00:00 2001 From: Jannik Streidl Date: Mon, 23 Sep 2024 15:48:12 +0200 Subject: [PATCH 23/47] enh: CitationsModal --- .../chat/Messages/CitationsModal.svelte | 36 ++++++++++++------- src/lib/components/common/Tooltip.svelte | 5 ++- src/lib/i18n/locales/de-DE/translation.json | 4 ++- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/lib/components/chat/Messages/CitationsModal.svelte b/src/lib/components/chat/Messages/CitationsModal.svelte index ecd1088a9..ced527166 100644 --- a/src/lib/components/chat/Messages/CitationsModal.svelte +++ b/src/lib/components/chat/Messages/CitationsModal.svelte @@ -1,6 +1,7 @@ -
-
- {#each Object.keys(groupedMessages) as modelIdx} - {#if groupedMessagesIdx[modelIdx] !== undefined && groupedMessages[modelIdx].messages.length > 0} - - - {@const message = groupedMessages[modelIdx].messages[groupedMessagesIdx[modelIdx]]} +{#if parentMessage} +
+
+ {#each Object.keys(groupedMessageIds) as modelIdx} + {#if groupedMessageIdsIdx[modelIdx] !== undefined && groupedMessageIds[modelIdx].messageIds.length > 0} + + + {@const _messageId = + groupedMessageIds[modelIdx].messageIds[groupedMessageIdsIdx[modelIdx]]} -
{ - if (currentMessageId != message.id) { - currentMessageId = message.id; - let messageId = message.id; - console.log(messageId); - // - let messageChildrenIds = history.messages[messageId].childrenIds; - while (messageChildrenIds.length !== 0) { - messageId = messageChildrenIds.at(-1); - messageChildrenIds = history.messages[messageId].childrenIds; +
{ + if (messageId != _messageId) { + let messageChildrenIds = history.messages[_messageId].childrenIds; + while (messageChildrenIds.length !== 0) { + messageId = messageChildrenIds.at(-1); + messageChildrenIds = history.messages[_messageId].childrenIds; + } + history.currentId = _messageId; + dispatch('change'); } - history.currentId = messageId; - dispatch('change'); - } - }} - > - {#key history.currentId} - {#if message} - m.id)} - isLastMessage={true} - {updateChatMessages} - {saveNewResponseMessage} - {confirmEditResponseMessage} - showPreviousMessage={() => showPreviousMessage(modelIdx)} - showNextMessage={() => showNextMessage(modelIdx)} - {readOnly} - {rateMessage} - {copyToClipboard} - {continueResponse} - regenerateResponse={async (message) => { - regenerateResponse(message); - await tick(); - groupedMessagesIdx[modelIdx] = groupedMessages[modelIdx].messages.length - 1; - }} - on:action={async (e) => { - dispatch('action', e.detail); - }} - on:save={async (e) => { - console.log('save', e); + }} + > + {#key history.currentId} + {#if message} + showPreviousMessage(modelIdx)} + showNextMessage={() => showNextMessage(modelIdx)} + {rateMessage} + {editMessage} + {continueResponse} + regenerateResponse={async (message) => { + regenerateResponse(message); + await tick(); + groupedMessageIdsIdx[modelIdx] = + groupedMessageIds[modelIdx].messageIds.length - 1; + }} + on:action={async (e) => { + dispatch('action', e.detail); + }} + on:update={async (e) => { + dispatch('update', e.detail); + }} + on:save={async (e) => { + dispatch('save', e.detail); + }} + {readOnly} + /> + {/if} + {/key} +
+ {/if} + {/each} +
- const message = e.detail; - history.messages[message.id] = message; - await updateChatById(localStorage.token, chatId, { - messages: messages, - history: history - }); - }} - /> + {#if !readOnly && isLastMessage} + {#if !Object.keys(groupedMessageIds).find((modelIdx) => { + const { messageIds } = groupedMessageIds[modelIdx]; + const _messageId = messageIds[groupedMessageIdsIdx[modelIdx]]; + return !history.messages[_messageId]?.done ?? false; + })} +
+
+ {#if history.messages[messageId]?.merged?.status} + {@const message = history.messages[messageId]?.merged} + +
+ + Merged Response + + {#if message.timestamp} + + {/if} + + +
+ {#if (message?.content ?? '') === ''} + + {:else} + + {/if} +
+
{/if} - {/key} +
+ +
+ + + +
{/if} - {/each} -
- - {#if !readOnly && isLastMessage} - {#if !Object.keys(groupedMessages).find((modelIdx) => { - const { messages } = groupedMessages[modelIdx]; - return !messages[groupedMessagesIdx[modelIdx]]?.done ?? false; - })} -
-
- {#if history.messages[currentMessageId]?.merged?.status} - {@const message = history.messages[currentMessageId]?.merged} - -
- - Merged Response - - {#if message.timestamp} - - {/if} - - -
- {#if (message?.content ?? '') === ''} - - {:else} - - {/if} -
-
- {/if} -
- -
- - - -
-
{/if} - {/if} -
+
+{/if} diff --git a/src/lib/components/chat/Messages/ResponseMessage.svelte b/src/lib/components/chat/Messages/ResponseMessage.svelte index c62c20b6b..6d010bd5a 100644 --- a/src/lib/components/chat/Messages/ResponseMessage.svelte +++ b/src/lib/components/chat/Messages/ResponseMessage.svelte @@ -77,15 +77,18 @@ annotation?: { type: string; rating: number }; } - export let message: MessageType; + export let history; + export let messageId; + + let message: MessageType = JSON.parse(JSON.stringify(history.messages[messageId])); + $: if (history.messages) { + if (JSON.stringify(message) !== JSON.stringify(history.messages[messageId])) { + message = JSON.parse(JSON.stringify(history.messages[messageId])); + } + } + export let siblings; - export let isLastMessage = true; - - export let readOnly = false; - - export let saveNewResponseMessage: Function = () => {}; - export let showPreviousMessage: Function; export let showNextMessage: Function; @@ -95,6 +98,9 @@ export let continueResponse: Function; export let regenerateResponse: Function; + export let isLastMessage = true; + export let readOnly = false; + let model = null; $: model = $models.find((m) => m.id === message.model); diff --git a/src/lib/components/chat/Messages/UserMessage.svelte b/src/lib/components/chat/Messages/UserMessage.svelte index 3f0fd7be9..709ce2d51 100644 --- a/src/lib/components/chat/Messages/UserMessage.svelte +++ b/src/lib/components/chat/Messages/UserMessage.svelte @@ -20,25 +20,30 @@ const i18n = getContext('i18n'); const dispatch = createEventDispatcher(); - export let user; - export let message; + + export let history; + export let messageId; + export let siblings; - export let isFirstMessage: boolean; export let showPreviousMessage: Function; export let showNextMessage: Function; export let editMessage: Function; + export let isFirstMessage: boolean; export let readOnly: boolean; let edit = false; let editedContent = ''; let messageEditTextAreaElement: HTMLTextAreaElement; - $: if (message) { - console.log('message', message); + let message = JSON.parse(JSON.stringify(history.messages[messageId])); + $: if (history.messages) { + if (JSON.stringify(message) !== JSON.stringify(history.messages[messageId])) { + message = JSON.parse(JSON.stringify(history.messages[messageId])); + } } const copyToClipboard = async (text) => { From 12f95555fc0f699458ebdaa5fb503342a2a16406 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Mon, 23 Sep 2024 23:23:08 +0200 Subject: [PATCH 27/47] fix --- src/lib/components/chat/Messages.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/components/chat/Messages.svelte b/src/lib/components/chat/Messages.svelte index 5a6bc0112..d342abf7f 100644 --- a/src/lib/components/chat/Messages.svelte +++ b/src/lib/components/chat/Messages.svelte @@ -216,6 +216,7 @@ if (submit) { // New response message const responseMessageId = uuidv4(); + const message = history.messages[messageId]; const parentId = message.parentId; const responseMessage = { From e06667ead8f183440131ecdd6ddee0572d98a60b Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Mon, 23 Sep 2024 23:39:33 +0200 Subject: [PATCH 28/47] refac --- src/lib/components/chat/ChatControls.svelte | 1 - src/lib/components/chat/Messages/CodeBlock.svelte | 15 ++++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/lib/components/chat/ChatControls.svelte b/src/lib/components/chat/ChatControls.svelte index 45c66f3e0..9cc44ce38 100644 --- a/src/lib/components/chat/ChatControls.svelte +++ b/src/lib/components/chat/ChatControls.svelte @@ -128,7 +128,6 @@ : 30 : 0} onResize={(size) => { - console.log(size); if (size === 0) { showControls.set(false); } else { diff --git a/src/lib/components/chat/Messages/CodeBlock.svelte b/src/lib/components/chat/Messages/CodeBlock.svelte index dbe49c232..15aea5e35 100644 --- a/src/lib/components/chat/Messages/CodeBlock.svelte +++ b/src/lib/components/chat/Messages/CodeBlock.svelte @@ -20,6 +20,8 @@ export let lang = ''; export let code = ''; + let _token = null; + let mermaidHtml = null; let highlightedCode = null; @@ -226,7 +228,7 @@ __builtins__.input = input`); } }; - $: if (token) { + const render = async () => { if (lang === 'mermaid' && (token?.raw ?? '').slice(-4).includes('```')) { (async () => { await drawMermaidDiagram(); @@ -242,6 +244,17 @@ __builtins__.input = input`); // Set a new timeout to debounce the code highlighting debounceTimeout = setTimeout(highlightCode, 10); } + }; + + $: if (token) { + if (JSON.stringify(token) !== JSON.stringify(_token)) { + console.log('hi'); + _token = token; + } + } + + $: if (_token) { + render(); } onMount(async () => { From f69956bda8bb11b9bfc1c0987f149a1243f5b592 Mon Sep 17 00:00:00 2001 From: "Jannik S." <69747628+jannikstdl@users.noreply.github.com> Date: Mon, 23 Sep 2024 23:43:50 +0200 Subject: [PATCH 29/47] fix: only append link with page attribute if metatada.page is available --- src/lib/components/chat/Messages/CitationsModal.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/chat/Messages/CitationsModal.svelte b/src/lib/components/chat/Messages/CitationsModal.svelte index ced527166..923fdea54 100644 --- a/src/lib/components/chat/Messages/CitationsModal.svelte +++ b/src/lib/components/chat/Messages/CitationsModal.svelte @@ -65,7 +65,7 @@ Date: Mon, 23 Sep 2024 23:52:45 +0200 Subject: [PATCH 30/47] refac --- .../chat/Messages/MultiResponseMessages.svelte | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/lib/components/chat/Messages/MultiResponseMessages.svelte b/src/lib/components/chat/Messages/MultiResponseMessages.svelte index 83ca78b3d..1bd4b8875 100644 --- a/src/lib/components/chat/Messages/MultiResponseMessages.svelte +++ b/src/lib/components/chat/Messages/MultiResponseMessages.svelte @@ -129,7 +129,7 @@ } else { return { ...a, - [modelIdx]: 0 + [modelIdx]: groupedMessageIds[modelIdx].messageIds.length - 1 }; } }, {}); @@ -149,7 +149,14 @@ }; onMount(async () => { - initHandler(); + await initHandler(); + await tick(); + + const messageElement = document.getElementById(`message-${messageId}`); + console.log(messageElement); + if (messageElement) { + messageElement.scrollIntoView({ behavior: 'smooth', block: 'center' }); + } }); From 93cb2be35d36e043c74cff1f274290dbed53e5db Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Mon, 23 Sep 2024 23:55:18 +0200 Subject: [PATCH 31/47] refac --- src/lib/components/chat/Chat.svelte | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index 25928ddd7..9b490eca8 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -210,6 +210,8 @@ } else { console.log('Unknown message type', data); } + + history.messages[event.message_id] = message; } }; From d7b64ff44779fb8168a3ec27f37f1aa33917653d Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Tue, 24 Sep 2024 00:27:22 +0200 Subject: [PATCH 32/47] enh: infinite scroll messages --- src/lib/components/chat/Messages.svelte | 33 ++++++++++++++++++++++--- src/lib/components/common/Loader.svelte | 22 ++++++++++++++--- 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/src/lib/components/chat/Messages.svelte b/src/lib/components/chat/Messages.svelte index d342abf7f..d6d2b881a 100644 --- a/src/lib/components/chat/Messages.svelte +++ b/src/lib/components/chat/Messages.svelte @@ -9,6 +9,8 @@ import Placeholder from './Messages/Placeholder.svelte'; import Message from './Messages/Message.svelte'; + import Loader from '../common/Loader.svelte'; + import Spinner from '../common/Spinner.svelte'; const i18n = getContext('i18n'); @@ -33,12 +35,21 @@ export let bottomPadding = false; export let autoScroll; + let messagesCount = 20; + let messagesLoading = false; + + const loadMoreMessages = async () => { + messagesLoading = true; + messagesCount += 20; + messagesLoading = false; + }; + $: if (history.currentId) { let _messages = []; let message = history.messages[history.currentId]; - while (message) { - _messages.unshift({ ...message }); + while (message && _messages.length <= messagesCount) { + _messages.push({ ...message }); message = message.parentId !== null ? history.messages[message.parentId] : null; } @@ -330,7 +341,7 @@ {:else}
{#key chatId} -
+
{#each messages as message, messageIdx (message.id)} {/each} + + {#if messages.at(-1).parentId !== null} + { + console.log('visible'); + if (!messagesLoading) { + loadMoreMessages(); + } + }} + > +
+ +
Loading...
+
+
+ {/if}
{#if bottomPadding} diff --git a/src/lib/components/common/Loader.svelte b/src/lib/components/common/Loader.svelte index 86c415ae4..ac7ecaf28 100644 --- a/src/lib/components/common/Loader.svelte +++ b/src/lib/components/common/Loader.svelte @@ -1,16 +1,24 @@
From ad82eae6a99df8c31475e54a49596a055f84075e Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Tue, 24 Sep 2024 00:57:28 +0200 Subject: [PATCH 33/47] feat: create new message pair on cmd+shift+enter --- src/lib/components/chat/Chat.svelte | 103 ++++++++++++++---- src/lib/components/chat/MessageInput.svelte | 7 ++ src/lib/components/chat/Messages.svelte | 36 +++--- .../components/chat/Messages/Message.svelte | 2 +- 4 files changed, 110 insertions(+), 38 deletions(-) diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index 9b490eca8..4f227c090 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -559,6 +559,66 @@ }, 1000); }; + const createMessagePair = async (userPrompt) => { + prompt = ''; + if (selectedModels.length === 0) { + toast.error($i18n.t('Model not selected')); + } else { + const modelId = selectedModels[0]; + const model = $models.filter((m) => m.id === modelId).at(0); + + const messages = createMessagesList(history.currentId); + const parentMessage = messages.length !== 0 ? messages.at(-1) : null; + + const userMessageId = uuidv4(); + const responseMessageId = uuidv4(); + + const userMessage = { + id: userMessageId, + parentId: parentMessage ? parentMessage.id : null, + childrenIds: [responseMessageId], + role: 'user', + content: userPrompt ? userPrompt : `[PROMPT] ${userMessageId}`, + timestamp: Math.floor(Date.now() / 1000) + }; + + const responseMessage = { + id: responseMessageId, + parentId: userMessageId, + childrenIds: [], + role: 'assistant', + content: `[RESPONSE] ${responseMessageId}`, + done: true, + + model: modelId, + modelName: model.name ?? model.id, + modelIdx: 0, + timestamp: Math.floor(Date.now() / 1000) + }; + + if (parentMessage) { + parentMessage.childrenIds.push(userMessageId); + history.messages[parentMessage.id] = parentMessage; + } + history.messages[userMessageId] = userMessage; + history.messages[responseMessageId] = responseMessage; + + history.currentId = responseMessageId; + + await tick(); + + if (autoScroll) { + scrollToBottom(); + } + + if (messages.length === 0) { + await initChatHandler(); + } else { + await saveChatHandler($chatId); + } + } + }; + ////////////////////////// // Chat functions ////////////////////////// @@ -666,25 +726,7 @@ history.messages[history.currentId].parentId === null && history.messages[history.currentId].role === 'user' ) { - if (!$temporaryChatEnabled) { - chat = await createNewChat(localStorage.token, { - id: $chatId, - title: $i18n.t('New Chat'), - models: selectedModels, - system: $settings.system ?? undefined, - params: params, - history: history, - tags: [], - timestamp: Date.now() - }); - - currentChatPage.set(1); - await chats.set(await getChatList(localStorage.token, $currentChatPage)); - await chatId.set(chat.id); - } else { - await chatId.set('local'); - } - await tick(); + await initChatHandler(); } let _responses: string[] = []; @@ -1718,6 +1760,28 @@ }); }; + const initChatHandler = async () => { + if (!$temporaryChatEnabled) { + chat = await createNewChat(localStorage.token, { + id: $chatId, + title: $i18n.t('New Chat'), + models: selectedModels, + system: $settings.system ?? undefined, + params: params, + history: history, + tags: [], + timestamp: Date.now() + }); + + currentChatPage.set(1); + await chats.set(await getChatList(localStorage.token, $currentChatPage)); + await chatId.set(chat.id); + } else { + await chatId.set('local'); + } + await tick(); + }; + const saveChatHandler = async (_chatId) => { if ($chatId == _chatId) { if (!$temporaryChatEnabled) { @@ -1861,6 +1925,7 @@ transparentBackground={$settings?.backgroundImageUrl ?? false} {submitPrompt} {stopResponse} + {createMessagePair} on:call={async () => { await showControls.set(true); }} diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index bb5250def..f474b755b 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -41,6 +41,7 @@ export let transparentBackground = false; export let submitPrompt: Function; + export let createMessagePair: Function; export let stopResponse: Function; export let autoScroll = false; @@ -554,6 +555,12 @@ const isCtrlPressed = e.ctrlKey || e.metaKey; // metaKey is for Cmd key on Mac const commandsContainerElement = document.getElementById('commands-container'); + // Command/Ctrl + Shift + Enter to submit a message pair + if (isCtrlPressed && e.key === 'Enter' && e.shiftKey) { + e.preventDefault(); + createMessagePair(prompt); + } + // Check if Ctrl + R is pressed if (prompt === '' && isCtrlPressed && e.key.toLowerCase() === 'r') { e.preventDefault(); diff --git a/src/lib/components/chat/Messages.svelte b/src/lib/components/chat/Messages.svelte index d6d2b881a..aa1cfb433 100644 --- a/src/lib/components/chat/Messages.svelte +++ b/src/lib/components/chat/Messages.svelte @@ -49,7 +49,7 @@ let message = history.messages[history.currentId]; while (message && _messages.length <= messagesCount) { - _messages.push({ ...message }); + _messages.unshift({ ...message }); message = message.parentId !== null ? history.messages[message.parentId] : null; } @@ -341,7 +341,23 @@ {:else}
{#key chatId} -
+
+ {#if messages.at(0)?.parentId !== null} + { + console.log('visible'); + if (!messagesLoading) { + loadMoreMessages(); + } + }} + > +
+ +
Loading...
+
+
+ {/if} + {#each messages as message, messageIdx (message.id)} {/each} - - {#if messages.at(-1).parentId !== null} - { - console.log('visible'); - if (!messagesLoading) { - loadMoreMessages(); - } - }} - > -
- -
Loading...
-
-
- {/if}
{#if bottomPadding} diff --git a/src/lib/components/chat/Messages/Message.svelte b/src/lib/components/chat/Messages/Message.svelte index dd5c498a3..3b07ef3db 100644 --- a/src/lib/components/chat/Messages/Message.svelte +++ b/src/lib/components/chat/Messages/Message.svelte @@ -41,7 +41,7 @@ export let readOnly = false; onMount(() => { - console.log('message', idx); + // console.log('message', idx); }); From 398bc96b1ad8e14fa6fdc3ff235e254d8ff8784a Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Tue, 24 Sep 2024 01:05:46 +0200 Subject: [PATCH 34/47] refac --- src/lib/components/chat/Messages.svelte | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lib/components/chat/Messages.svelte b/src/lib/components/chat/Messages.svelte index aa1cfb433..a8d0abf13 100644 --- a/src/lib/components/chat/Messages.svelte +++ b/src/lib/components/chat/Messages.svelte @@ -39,8 +39,15 @@ let messagesLoading = false; const loadMoreMessages = async () => { + // scroll slightly down to disable continuous loading + const element = document.getElementById('messages-container'); + element.scrollTop = element.scrollTop + 100; + messagesLoading = true; messagesCount += 20; + + await tick(); + messagesLoading = false; }; From fdf02c4e865a7bcaa1db27c90e746cddc068ceac Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Tue, 24 Sep 2024 01:12:49 +0200 Subject: [PATCH 35/47] fix --- src/lib/components/chat/Chat.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index 4f227c090..c698698ce 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -1535,7 +1535,7 @@ ); } - history.messages[responseMessageId] = responseMessage; + history.messages[responseMessage.id] = responseMessage; }; const stopResponse = () => { From 822c47c171a0b7e0aba1c6c0e7ddc8506d9b19a9 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Tue, 24 Sep 2024 01:35:34 +0200 Subject: [PATCH 36/47] fix --- .../components/chat/Messages/MultiResponseMessages.svelte | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/lib/components/chat/Messages/MultiResponseMessages.svelte b/src/lib/components/chat/Messages/MultiResponseMessages.svelte index 1bd4b8875..a070abd5d 100644 --- a/src/lib/components/chat/Messages/MultiResponseMessages.svelte +++ b/src/lib/components/chat/Messages/MultiResponseMessages.svelte @@ -49,9 +49,10 @@ const showPreviousMessage = (modelIdx) => { groupedMessageIdsIdx[modelIdx] = Math.max(0, groupedMessageIdsIdx[modelIdx] - 1); - let messageId = groupedMessageIds[modelIdx].messages[groupedMessageIdsIdx[modelIdx]].id; + let messageId = groupedMessageIds[modelIdx].messageIds[groupedMessageIdsIdx[modelIdx]]; console.log(messageId); + let messageChildrenIds = history.messages[messageId].childrenIds; while (messageChildrenIds.length !== 0) { @@ -65,11 +66,11 @@ const showNextMessage = (modelIdx) => { groupedMessageIdsIdx[modelIdx] = Math.min( - groupedMessageIds[modelIdx].messages.length - 1, + groupedMessageIds[modelIdx].messageIds.length - 1, groupedMessageIdsIdx[modelIdx] + 1 ); - let messageId = groupedMessageIds[modelIdx].messages[groupedMessageIdsIdx[modelIdx]].id; + let messageId = groupedMessageIds[modelIdx].messageIds[groupedMessageIdsIdx[modelIdx]]; console.log(messageId); let messageChildrenIds = history.messages[messageId].childrenIds; From 0d01ea5f2fa3f5692ed94a88a7ab9b67a61bf62c Mon Sep 17 00:00:00 2001 From: kivvi Date: Tue, 24 Sep 2024 11:51:47 +0800 Subject: [PATCH 37/47] Set whether to stream responses for this model individually, overriding the global setting --- src/lib/components/chat/Chat.svelte | 2 +- .../Settings/Advanced/AdvancedParams.svelte | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index b6a90a953..54b24dfec 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -1206,7 +1206,7 @@ await tick(); try { - const stream = $settings?.streamResponse ?? true; + const stream = model?.info?.params?.stream_response ?? $settings?.streamResponse ?? true; const [res, controller] = await generateOpenAIChatCompletion( localStorage.token, { diff --git a/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte b/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte index d1b566b63..8f3a3973b 100644 --- a/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte +++ b/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte @@ -10,6 +10,7 @@ export let params = { // Advanced + stream_response: null, // Set stream responses for this model individually seed: null, stop: null, temperature: null, @@ -42,6 +43,30 @@
+
+
+
+ {$i18n.t('Stream Chat Response')} +
+ + +
+
+
{$i18n.t('Seed')}
From 40d7d7d6dd7049e900d9ff301276db95eacac76c Mon Sep 17 00:00:00 2001 From: kivvi Date: Tue, 24 Sep 2024 11:51:47 +0800 Subject: [PATCH 38/47] Set whether to stream responses for this model individually, overriding the global setting --- src/lib/components/chat/Chat.svelte | 4 +-- .../Settings/Advanced/AdvancedParams.svelte | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index b6a90a953..45577520a 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -912,7 +912,7 @@ await tick(); - const stream = $settings?.streamResponse ?? true; + const stream = model?.info?.params?.stream_response ?? $settings?.streamResponse ?? true; const [res, controller] = await generateChatCompletion(localStorage.token, { stream: stream, model: model.id, @@ -1206,7 +1206,7 @@ await tick(); try { - const stream = $settings?.streamResponse ?? true; + const stream = model?.info?.params?.stream_response ?? $settings?.streamResponse ?? true; const [res, controller] = await generateOpenAIChatCompletion( localStorage.token, { diff --git a/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte b/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte index d1b566b63..8f3a3973b 100644 --- a/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte +++ b/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte @@ -10,6 +10,7 @@ export let params = { // Advanced + stream_response: null, // Set stream responses for this model individually seed: null, stop: null, temperature: null, @@ -42,6 +43,30 @@
+
+
+
+ {$i18n.t('Stream Chat Response')} +
+ + +
+
+
{$i18n.t('Seed')}
From fdd27aa3213f7fa4b4cbc3455a7a520a92d254b3 Mon Sep 17 00:00:00 2001 From: Etienne Perot Date: Mon, 23 Sep 2024 23:22:47 -0700 Subject: [PATCH 39/47] fix: close temporary file after creating it. This fixes "The process cannot access the file because it is being used by another process" errors on Windows. The file is still automatically deleted by the `os.unlink` call later in the function. Updates #5606 Fixes #5642 --- backend/open_webui/apps/webui/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/open_webui/apps/webui/utils.py b/backend/open_webui/apps/webui/utils.py index 8bf48e400..969d5622c 100644 --- a/backend/open_webui/apps/webui/utils.py +++ b/backend/open_webui/apps/webui/utils.py @@ -87,7 +87,7 @@ def load_toolkit_module_by_id(toolkit_id, content=None): # Create a temporary file and use it to define `__file__` so # that it works as expected from the module's perspective. temp_file = tempfile.NamedTemporaryFile(delete=False) - + temp_file.close() try: with open(temp_file.name, "w", encoding="utf-8") as f: f.write(content) @@ -131,6 +131,7 @@ def load_function_module_by_id(function_id, content=None): # Create a temporary file and use it to define `__file__` so # that it works as expected from the module's perspective. temp_file = tempfile.NamedTemporaryFile(delete=False) + temp_file.close() try: with open(temp_file.name, "w", encoding="utf-8") as f: f.write(content) From 33d8d818bd7eca64b654fdb453224a9e7322bc9f Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Tue, 24 Sep 2024 10:54:49 +0200 Subject: [PATCH 40/47] fix --- src/lib/components/chat/Messages/MultiResponseMessages.svelte | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/components/chat/Messages/MultiResponseMessages.svelte b/src/lib/components/chat/Messages/MultiResponseMessages.svelte index a070abd5d..7e1e7d30f 100644 --- a/src/lib/components/chat/Messages/MultiResponseMessages.svelte +++ b/src/lib/components/chat/Messages/MultiResponseMessages.svelte @@ -143,8 +143,9 @@ const mergeResponsesHandler = async () => { const responses = Object.keys(groupedMessageIds).map((modelIdx) => { const { messageIds } = groupedMessageIds[modelIdx]; + const messageId = messageIds[groupedMessageIdsIdx[modelIdx]]; - return messages[groupedMessageIdsIdx[modelIdx]].content; + return history.messages[messageId].content; }); mergeResponses(messageId, responses, chatId); }; From e268ee56756df387a60fa756035a41cc3cf78040 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Tue, 24 Sep 2024 11:00:47 +0200 Subject: [PATCH 41/47] enh: audio/x-m4a support --- backend/open_webui/apps/audio/main.py | 2 +- src/lib/components/chat/MessageInput.svelte | 2 +- src/lib/components/workspace/Documents.svelte | 2 +- src/lib/constants.ts | 4 +++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/backend/open_webui/apps/audio/main.py b/backend/open_webui/apps/audio/main.py index 0eee533bd..a1e6e94fa 100644 --- a/backend/open_webui/apps/audio/main.py +++ b/backend/open_webui/apps/audio/main.py @@ -360,7 +360,7 @@ def transcribe( ): log.info(f"file.content_type: {file.content_type}") - if file.content_type not in ["audio/mpeg", "audio/wav", "audio/ogg"]: + if file.content_type not in ["audio/mpeg", "audio/wav", "audio/ogg", "audio/x-m4a"]: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.FILE_NOT_SUPPORTED, diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index f474b755b..ea6b0aec8 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -107,7 +107,7 @@ files = [...files, fileItem]; // Check if the file is an audio file and transcribe/convert it to text file - if (['audio/mpeg', 'audio/wav', 'audio/ogg'].includes(file['type'])) { + if (['audio/mpeg', 'audio/wav', 'audio/ogg', 'audio/x-m4a'].includes(file['type'])) { const res = await transcribeAudio(localStorage.token, file).catch((error) => { toast.error(error); return null; diff --git a/src/lib/components/workspace/Documents.svelte b/src/lib/components/workspace/Documents.svelte index f1e77bddd..38f46f745 100644 --- a/src/lib/components/workspace/Documents.svelte +++ b/src/lib/components/workspace/Documents.svelte @@ -55,7 +55,7 @@ const uploadDoc = async (file, tags?: object) => { console.log(file); // Check if the file is an audio file and transcribe/convert it to text file - if (['audio/mpeg', 'audio/wav', 'audio/ogg'].includes(file['type'])) { + if (['audio/mpeg', 'audio/wav', 'audio/ogg', 'audio/x-m4a'].includes(file['type'])) { const transcribeRes = await transcribeAudio(localStorage.token, file).catch((error) => { toast.error(error); return null; diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 5fc1e7b19..ad7b5c29e 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -31,7 +31,9 @@ export const SUPPORTED_FILE_TYPE = [ 'application/x-javascript', 'text/markdown', 'audio/mpeg', - 'audio/wav' + 'audio/wav', + 'audio/ogg', + 'audio/x-m4a' ]; export const SUPPORTED_FILE_EXTENSIONS = [ From f6add9270297c4cea4c5cd84bf0962a7002fd67f Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Tue, 24 Sep 2024 11:35:51 +0200 Subject: [PATCH 42/47] chore: format --- .../chat/Settings/Advanced/AdvancedParams.svelte | 11 ++++++++--- src/lib/i18n/locales/ar-BH/translation.json | 2 ++ src/lib/i18n/locales/bg-BG/translation.json | 2 ++ src/lib/i18n/locales/bn-BD/translation.json | 2 ++ src/lib/i18n/locales/ca-ES/translation.json | 2 ++ src/lib/i18n/locales/ceb-PH/translation.json | 2 ++ src/lib/i18n/locales/de-DE/translation.json | 6 +++--- src/lib/i18n/locales/dg-DG/translation.json | 2 ++ src/lib/i18n/locales/en-GB/translation.json | 2 ++ src/lib/i18n/locales/en-US/translation.json | 2 ++ src/lib/i18n/locales/es-ES/translation.json | 2 ++ src/lib/i18n/locales/fa-IR/translation.json | 2 ++ src/lib/i18n/locales/fi-FI/translation.json | 2 ++ src/lib/i18n/locales/fr-CA/translation.json | 2 ++ src/lib/i18n/locales/fr-FR/translation.json | 2 ++ src/lib/i18n/locales/he-IL/translation.json | 2 ++ src/lib/i18n/locales/hi-IN/translation.json | 2 ++ src/lib/i18n/locales/hr-HR/translation.json | 2 ++ src/lib/i18n/locales/id-ID/translation.json | 2 ++ src/lib/i18n/locales/it-IT/translation.json | 2 ++ src/lib/i18n/locales/ja-JP/translation.json | 2 ++ src/lib/i18n/locales/ka-GE/translation.json | 2 ++ src/lib/i18n/locales/ko-KR/translation.json | 2 ++ src/lib/i18n/locales/lt-LT/translation.json | 2 ++ src/lib/i18n/locales/ms-MY/translation.json | 2 ++ src/lib/i18n/locales/nb-NO/translation.json | 2 ++ src/lib/i18n/locales/nl-NL/translation.json | 2 ++ src/lib/i18n/locales/pa-IN/translation.json | 2 ++ src/lib/i18n/locales/pl-PL/translation.json | 2 ++ src/lib/i18n/locales/pt-BR/translation.json | 2 ++ src/lib/i18n/locales/pt-PT/translation.json | 2 ++ src/lib/i18n/locales/ro-RO/translation.json | 2 ++ src/lib/i18n/locales/ru-RU/translation.json | 2 ++ src/lib/i18n/locales/sr-RS/translation.json | 2 ++ src/lib/i18n/locales/sv-SE/translation.json | 2 ++ src/lib/i18n/locales/th-TH/translation.json | 2 ++ src/lib/i18n/locales/tk-TW/translation.json | 2 ++ src/lib/i18n/locales/tr-TR/translation.json | 2 ++ src/lib/i18n/locales/uk-UA/translation.json | 2 ++ src/lib/i18n/locales/vi-VN/translation.json | 2 ++ src/lib/i18n/locales/zh-CN/translation.json | 2 ++ src/lib/i18n/locales/zh-TW/translation.json | 2 ++ 42 files changed, 91 insertions(+), 6 deletions(-) diff --git a/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte b/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte index 9766d3458..df897ec0e 100644 --- a/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte +++ b/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte @@ -10,7 +10,7 @@ export let params = { // Advanced - stream_response: null, // Set stream responses for this model individually + stream_response: null, // Set stream responses for this model individually seed: null, stop: null, temperature: null, @@ -52,8 +52,13 @@ +
+
diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte index 9175cf002..a59d0bd53 100644 --- a/src/routes/(app)/+layout.svelte +++ b/src/routes/(app)/+layout.svelte @@ -9,7 +9,7 @@ import { goto } from '$app/navigation'; - import { getModels as _getModels } from '$lib/apis'; + import { getModels as _getModels, getVersionUpdates } from '$lib/apis'; import { getAllChatTags } from '$lib/apis/chats'; import { getPrompts } from '$lib/apis/prompts'; @@ -42,6 +42,10 @@ import AccountPending from '$lib/components/layout/Overlay/AccountPending.svelte'; import { getFunctions } from '$lib/apis/functions'; import { page } from '$app/stores'; + import { WEBUI_VERSION } from '$lib/constants'; + import { compareVersion } from '$lib/utils'; + + import UpdateInfoToast from '$lib/components/layout/UpdateInfoToast.svelte'; const i18n = getContext('i18n'); @@ -191,11 +195,34 @@ temporaryChatEnabled.set(true); } + if ($user.role === 'admin') { + checkForVersionUpdates(); + } + await tick(); } loaded = true; }); + + const checkForVersionUpdates = async () => { + const version = await getVersionUpdates(localStorage.token).catch((error) => { + return { + current: WEBUI_VERSION, + latest: WEBUI_VERSION + }; + }); + + if (compareVersion(version.latest, version.current)) { + toast.custom(UpdateInfoToast, { + duration: Number.POSITIVE_INFINITY, + position: 'bottom-right', + componentProps: { + version + } + }); + } + }; diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index b71ac0d79..d1c30a96b 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -209,4 +209,14 @@ {/if} - + From ff00815b6196ed49c8b1f8014b69f91482dbe422 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Tue, 24 Sep 2024 12:41:44 +0200 Subject: [PATCH 44/47] chore: format --- src/lib/components/layout/UpdateInfoToast.svelte | 4 ++-- src/lib/i18n/locales/ar-BH/translation.json | 2 ++ src/lib/i18n/locales/bg-BG/translation.json | 2 ++ src/lib/i18n/locales/bn-BD/translation.json | 2 ++ src/lib/i18n/locales/ca-ES/translation.json | 2 ++ src/lib/i18n/locales/ceb-PH/translation.json | 2 ++ src/lib/i18n/locales/de-DE/translation.json | 2 ++ src/lib/i18n/locales/dg-DG/translation.json | 2 ++ src/lib/i18n/locales/en-GB/translation.json | 2 ++ src/lib/i18n/locales/en-US/translation.json | 2 ++ src/lib/i18n/locales/es-ES/translation.json | 2 ++ src/lib/i18n/locales/fa-IR/translation.json | 2 ++ src/lib/i18n/locales/fi-FI/translation.json | 2 ++ src/lib/i18n/locales/fr-CA/translation.json | 2 ++ src/lib/i18n/locales/fr-FR/translation.json | 2 ++ src/lib/i18n/locales/he-IL/translation.json | 2 ++ src/lib/i18n/locales/hi-IN/translation.json | 2 ++ src/lib/i18n/locales/hr-HR/translation.json | 2 ++ src/lib/i18n/locales/id-ID/translation.json | 2 ++ src/lib/i18n/locales/it-IT/translation.json | 2 ++ src/lib/i18n/locales/ja-JP/translation.json | 2 ++ src/lib/i18n/locales/ka-GE/translation.json | 2 ++ src/lib/i18n/locales/ko-KR/translation.json | 2 ++ src/lib/i18n/locales/lt-LT/translation.json | 2 ++ src/lib/i18n/locales/ms-MY/translation.json | 2 ++ src/lib/i18n/locales/nb-NO/translation.json | 2 ++ src/lib/i18n/locales/nl-NL/translation.json | 2 ++ src/lib/i18n/locales/pa-IN/translation.json | 2 ++ src/lib/i18n/locales/pl-PL/translation.json | 2 ++ src/lib/i18n/locales/pt-BR/translation.json | 2 ++ src/lib/i18n/locales/pt-PT/translation.json | 2 ++ src/lib/i18n/locales/ro-RO/translation.json | 2 ++ src/lib/i18n/locales/ru-RU/translation.json | 2 ++ src/lib/i18n/locales/sr-RS/translation.json | 2 ++ src/lib/i18n/locales/sv-SE/translation.json | 2 ++ src/lib/i18n/locales/th-TH/translation.json | 2 ++ src/lib/i18n/locales/tk-TW/translation.json | 2 ++ src/lib/i18n/locales/tr-TR/translation.json | 2 ++ src/lib/i18n/locales/uk-UA/translation.json | 2 ++ src/lib/i18n/locales/vi-VN/translation.json | 2 ++ src/lib/i18n/locales/zh-CN/translation.json | 2 ++ src/lib/i18n/locales/zh-TW/translation.json | 2 ++ 42 files changed, 84 insertions(+), 2 deletions(-) diff --git a/src/lib/components/layout/UpdateInfoToast.svelte b/src/lib/components/layout/UpdateInfoToast.svelte index ef587742f..3b8eb3020 100644 --- a/src/lib/components/layout/UpdateInfoToast.svelte +++ b/src/lib/components/layout/UpdateInfoToast.svelte @@ -17,8 +17,8 @@ class="flex items-start bg-[--info-bg] border border-[--info-border] text-[--info-text] rounded-lg px-3.5 py-3 text-xs" >
- {$i18n.t(`A new version (v{{VERSION_LATEST}}) is now available.`, { - VERSION_LATEST: version.latest + {$i18n.t(`A new version (v{{LATEST_VERSION}}) is now available.`, { + LATEST_VERSION: version.latest })} Date: Tue, 24 Sep 2024 12:49:35 +0200 Subject: [PATCH 45/47] refac: deprecate interface "stream response" settings for advanced params --- src/lib/components/chat/Chat.svelte | 13 ++++++-- .../Settings/Advanced/AdvancedParams.svelte | 2 +- .../components/chat/Settings/General.svelte | 2 ++ .../components/chat/Settings/Interface.svelte | 30 ------------------- 4 files changed, 14 insertions(+), 33 deletions(-) diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index 2ed489e45..4e521f789 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -952,7 +952,11 @@ await tick(); - const stream = model?.info?.params?.stream_response ?? $settings?.streamResponse ?? true; + const stream = + model?.info?.params?.stream_response ?? + $settings?.params?.stream_response ?? + params?.stream_response ?? + true; const [res, controller] = await generateChatCompletion(localStorage.token, { stream: stream, model: model.id, @@ -1248,7 +1252,12 @@ await tick(); try { - const stream = model?.info?.params?.stream_response ?? $settings?.streamResponse ?? true; + const stream = + model?.info?.params?.stream_response ?? + $settings?.params?.stream_response ?? + params?.stream_response ?? + true; + const [res, controller] = await generateOpenAIChatCompletion( localStorage.token, { diff --git a/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte b/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte index df897ec0e..95b27b889 100644 --- a/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte +++ b/src/lib/components/chat/Settings/Advanced/AdvancedParams.svelte @@ -45,7 +45,7 @@
-
+
{$i18n.t('Stream Chat Response')}
diff --git a/src/lib/components/chat/Settings/General.svelte b/src/lib/components/chat/Settings/General.svelte index c308b9005..ee04deeb1 100644 --- a/src/lib/components/chat/Settings/General.svelte +++ b/src/lib/components/chat/Settings/General.svelte @@ -45,6 +45,7 @@ let params = { // Advanced + stream_response: null, seed: null, temperature: null, frequency_penalty: null, @@ -327,6 +328,7 @@ saveSettings({ system: system !== '' ? system : undefined, params: { + stream_response: params.stream_response !== null ? params.stream_response : undefined, seed: (params.seed !== null ? params.seed : undefined) ?? undefined, stop: params.stop ? params.stop.split(',').filter((e) => e) : undefined, temperature: params.temperature !== null ? params.temperature : undefined, diff --git a/src/lib/components/chat/Settings/Interface.svelte b/src/lib/components/chat/Settings/Interface.svelte index 139474c8a..58de9be4c 100644 --- a/src/lib/components/chat/Settings/Interface.svelte +++ b/src/lib/components/chat/Settings/Interface.svelte @@ -36,18 +36,11 @@ let voiceInterruption = false; let hapticFeedback = false; - let streamResponse = true; - const toggleSplitLargeChunks = async () => { splitLargeChunks = !splitLargeChunks; saveSettings({ splitLargeChunks: splitLargeChunks }); }; - const toggleStreamResponse = async () => { - streamResponse = !streamResponse; - saveSettings({ streamResponse: streamResponse }); - }; - const togglesScrollOnBranchChange = async () => { scrollOnBranchChange = !scrollOnBranchChange; saveSettings({ scrollOnBranchChange: scrollOnBranchChange }); @@ -165,7 +158,6 @@ userLocation = $settings.userLocation ?? false; hapticFeedback = $settings.hapticFeedback ?? false; - streamResponse = $settings?.streamResponse ?? true; defaultModelId = $settings?.models?.at(0) ?? ''; if ($config?.default_models) { @@ -319,28 +311,6 @@
-
-
-
- {$i18n.t('Stream Chat Response')} -
- - -
-
-
From e24ab4c6d2146b057179f13825f3a617f27ee7e6 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Tue, 24 Sep 2024 13:23:34 +0200 Subject: [PATCH 46/47] doc: changelog --- CHANGELOG.md | 29 +++++++++++++++++++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0008d21ec..758a45979 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,35 @@ 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/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.3.24] - 2024-09-24 + +### Added + +- **🚀 Rendering Optimization**: Significantly improved message rendering performance, enhancing user experience and webui responsiveness. +- **💖 Favorite Response Feature in Chat Overview**: Users can now mark responses as favorite directly from the chat overview, enhancing ease of retrieval and organization of preferred responses. +- **💬 Create Message Pairs with Shortcut**: Implemented creation of new message pairs using Cmd/Ctrl+Shift+Enter, making conversation editing faster and more intuitive. +- **🌍 Expanded User Prompt Variables**: Added weekday, timezone, and language information variables to user prompts to match system prompt variables. +- **🎵 Enhanced Audio Support**: Now includes support for 'audio/x-m4a' files, broadening compatibility with audio content within the platform. +- **🔏 Model URL Search Parameter**: Added an ability to select a model directly via URL parameters, streamlining navigation and model access. +- **📄 Enhanced PDF Citations**: PDF citations now open at the associated page, streamlining reference checks and document handling. +- **🔧Use of Redis in Sockets**: Enhanced socket implementation to fully support Redis, enabling effective stateless instances suitable for scalable load balancing. +- **🌍 Stream Individual Model Responses**: Allows specific models to have individualized streaming settings, enhancing performance and customization. +- **🕒 Display Model Hash and Last Modified Timestamp for Ollama Models**: Provides critical model details directly in the Models workspace for enhanced tracking. +- **❗ Update Info Notification for Admins**: Ensures administrators receive immediate updates upon login, keeping them informed of the latest changes and system statuses. + +### Fixed + +- **🗑️ Temporary File Handling On Windows**: Fixed an issue causing errors when accessing a temporary file being used by another process, Tools & Functions should now work as intended. +- **🔓 Authentication Toggle Issue**: Resolved the malfunction where setting 'WEBUI_AUTH=False' did not appropriately disable authentication, ensuring that user experience and system security settings function as configured. +- **🔧 Save As Copy Issue for Many Model Chats**: Resolved an error preventing users from save messages as copies in many model chats. +- **🔒 Sidebar Closure on Mobile**: Resolved an issue where the mobile sidebar remained open after menu engagement, improving user interface responsivity and comfort. +- **🛡️ Tooltip XSS Vulnerability**: Resolved a cross-site scripting (XSS) issue within tooltips, ensuring enhanced security and data integrity during user interactions. + +### Changed + +- **↩️ Deprecated Interface Stream Response Settings**: Moved to advanced parameters to streamline interface settings and enhance user clarity. +- **⚙️ Renamed 'speedRate' to 'playbackRate'**: Standardizes terminology, improving usability and understanding in media settings. + ## [0.3.23] - 2024-09-21 ### Added diff --git a/package-lock.json b/package-lock.json index 100a5ee3f..bd975a9e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "open-webui", - "version": "0.3.23", + "version": "0.3.24", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "open-webui", - "version": "0.3.23", + "version": "0.3.24", "dependencies": { "@codemirror/lang-javascript": "^6.2.2", "@codemirror/lang-python": "^6.1.6", diff --git a/package.json b/package.json index 8b314654e..dddd0b0b1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "open-webui", - "version": "0.3.23", + "version": "0.3.24", "private": true, "scripts": { "dev": "npm run pyodide:fetch && vite dev --host", From 31b311c3c998ce7fbf6ed4d1a5885ab19910f024 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Tue, 24 Sep 2024 13:28:00 +0200 Subject: [PATCH 47/47] refac Co-Authored-By: MicroDev <70126934+microdev1@users.noreply.github.com> --- backend/open_webui/main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/open_webui/main.py b/backend/open_webui/main.py index 64b7f2153..2ded77f2f 100644 --- a/backend/open_webui/main.py +++ b/backend/open_webui/main.py @@ -2329,10 +2329,11 @@ async def get_manifest_json(): return { "name": WEBUI_NAME, "short_name": WEBUI_NAME, + "description": "Open WebUI is an open, extensible, user-friendly interface for AI that adapts to your workflow.", "start_url": "/", "display": "standalone", "background_color": "#343541", - "orientation": "portrait-primary", + "orientation": "any", "icons": [ { "src": "/static/logo.png",