From fd5e8b4fcfe01e8d9eeb27b4377df245e82a66c8 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Mon, 23 Sep 2024 00:55:13 +0200 Subject: [PATCH 1/6] refac: deprecate messages for history --- src/lib/components/chat/Chat.svelte | 167 +++++++++--------- src/lib/components/chat/MessageInput.svelte | 13 +- src/lib/components/chat/Messages.svelte | 147 ++------------- .../components/chat/Messages/Message.svelte | 156 ++++++++++++++++ .../Messages/MultiResponseMessages.svelte | 142 +++++++-------- 5 files changed, 326 insertions(+), 299 deletions(-) create mode 100644 src/lib/components/chat/Messages/Message.svelte diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index 0b848b3cd..f9e23ca2f 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -5,6 +5,8 @@ import { PaneGroup, Pane, PaneResizer } from 'paneforge'; import { getContext, onDestroy, onMount, tick } from 'svelte'; + const i18n: Writable = getContext('i18n'); + import { goto } from '$app/navigation'; import { page } from '$app/stores'; @@ -67,11 +69,9 @@ import Navbar from '$lib/components/layout/Navbar.svelte'; import ChatControls from './ChatControls.svelte'; import EventConfirmDialog from '../common/ConfirmDialog.svelte'; - import EllipsisVertical from '../icons/EllipsisVertical.svelte'; - - const i18n: Writable = getContext('i18n'); export let chatIdProp = ''; + let loaded = false; const eventTarget = new EventTarget(); let controlPane; @@ -89,9 +89,10 @@ let eventConfirmationInputValue = ''; let eventCallback = null; + let chatIdUnsubscriber: Unsubscriber | undefined; + let selectedModels = ['']; let atSelectedModel: Model | undefined; - let selectedModelIds = []; $: selectedModelIds = atSelectedModel !== undefined ? [atSelectedModel.id] : selectedModels; @@ -102,35 +103,17 @@ let tags = []; let title = ''; - let prompt = ''; - - let chatFiles = []; - let files = []; - let messages = []; let history = { messages: {}, currentId: null }; + // Chat Input + let prompt = ''; + let chatFiles = []; + let files = []; let params = {}; - let chatIdUnsubscriber: Unsubscriber | undefined; - - $: if (history.currentId !== null) { - let _messages = []; - let currentMessage = history.messages[history.currentId]; - while (currentMessage) { - _messages.unshift({ ...currentMessage }); - currentMessage = - currentMessage.parentId !== null ? history.messages[currentMessage.parentId] : null; - } - - // This is most likely causing the performance issue - messages = _messages; - } else { - messages = []; - } - $: if (chatIdProp) { (async () => { console.log(chatIdProp); @@ -227,8 +210,6 @@ } else { console.log('Unknown message type', data); } - - messages = messages; } }; @@ -310,6 +291,9 @@ showOverview.set(false); } }); + + const chatInput = document.getElementById('chat-textarea'); + chatInput?.focus(); }); onDestroy(() => { @@ -331,7 +315,6 @@ autoScroll = true; title = ''; - messages = []; history = { messages: {}, currentId: null @@ -428,8 +411,8 @@ autoScroll = true; await tick(); - if (messages.length > 0) { - history.messages[messages.at(-1).id].done = true; + if (history.currentId) { + history.messages[history.currentId].done = true; } await tick(); @@ -448,8 +431,12 @@ }; const createMessagesList = (responseMessageId) => { + if (responseMessageId === null) { + return []; + } + const message = history.messages[responseMessageId]; - if (message.parentId) { + if (message?.parentId) { return [...createMessagesList(message.parentId), message]; } else { return [message]; @@ -510,6 +497,8 @@ }; const chatActionHandler = async (chatId, actionId, modelId, responseMessageId, event = null) => { + const messages = createMessagesList(responseMessageId); + const res = await chatAction(localStorage.token, actionId, { model: modelId, messages: messages.map((m) => ({ @@ -575,6 +564,7 @@ const submitPrompt = async (userPrompt, { _raw = false } = {}) => { let _responses = []; console.log('submitPrompt', $chatId); + const messages = createMessagesList(history.currentId); selectedModels = selectedModels.map((modelId) => $models.map((m) => m.id).includes(modelId) ? modelId : '' @@ -668,8 +658,34 @@ parentId: string, { modelId = null, modelIdx = null, newChat = false } = {} ) => { - let _responses: string[] = []; + // Create new chat if newChat is true and first user message + if ( + newChat && + 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(); + } + + let _responses: string[] = []; // If modelId is provided, use it, else use selected model let selectedModelIds = modelId ? [modelId] @@ -714,38 +730,14 @@ } await tick(); - // Create new chat if only one message in messages - if (newChat && messages.length == 2) { - if (!$temporaryChatEnabled) { - chat = await createNewChat(localStorage.token, { - id: $chatId, - title: $i18n.t('New Chat'), - models: selectedModels, - system: $settings.system ?? undefined, - params: params, - messages: messages, - 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 _chatId = JSON.parse(JSON.stringify($chatId)); - await Promise.all( selectedModelIds.map(async (modelId, _modelIdx) => { console.log('modelId', modelId); const model = $models.filter((m) => m.id === modelId).at(0); if (model) { + const messages = createMessagesList(parentId); // If there are image files, check if model is vision capable const hasImages = messages.some((message) => message.files?.some((file) => file.type === 'image') @@ -844,7 +836,7 @@ }` } : undefined, - ...messages + ...createMessagesList(responseMessageId) ] .filter((message) => message?.content?.trim()) .map((message) => { @@ -895,7 +887,7 @@ } ]; files.push(...model.info.meta.knowledge); - messages = messages; // Trigger Svelte update + history.messages[responseMessageId] = responseMessage; } files.push( ...(userMessage?.files ?? []).filter((item) => @@ -969,7 +961,7 @@ const { value, done } = await reader.read(); if (done || stopResponseFlag || _chatId !== $chatId) { responseMessage.done = true; - messages = messages; + history.messages[responseMessageId] = responseMessage; if (stopResponseFlag) { controller.abort('User: Stop Response'); @@ -1036,7 +1028,7 @@ ); } - messages = messages; + history.messages[responseMessageId] = responseMessage; } } else { responseMessage.done = true; @@ -1059,7 +1051,8 @@ eval_count: data.eval_count, eval_duration: data.eval_duration }; - messages = messages; + + history.messages[responseMessageId] = responseMessage; if ($settings.notificationEnabled && !document.hasFocus()) { const notification = new Notification(`${model.id}`, { @@ -1128,7 +1121,7 @@ ); } - messages = messages; + history.messages[responseMessageId] = responseMessage; } await saveChatHandler(_chatId); @@ -1161,7 +1154,8 @@ scrollToBottom(); } - if (messages.length == 2 && messages.at(1).content !== '' && selectedModels[0] === model.id) { + const messages = createMessagesList(responseMessageId); + if (messages.length == 2 && messages.at(-1).content !== '' && selectedModels[0] === model.id) { window.history.replaceState(history.state, '', `/c/${_chatId}`); const _title = await generateChatTitle(userPrompt); await setChatTitle(_chatId, _title); @@ -1189,7 +1183,7 @@ } ]; files.push(...model.info.meta.knowledge); - messages = messages; // Trigger Svelte update + history.messages[responseMessageId] = responseMessage; } files.push( ...(userMessage?.files ?? []).filter((item) => @@ -1240,7 +1234,7 @@ }` } : undefined, - ...messages + ...createMessagesList(responseMessageId) ] .filter((message) => message?.content?.trim()) .map((message, idx, arr) => ({ @@ -1318,7 +1312,7 @@ } if (done || stopResponseFlag || _chatId !== $chatId) { responseMessage.done = true; - messages = messages; + history.messages[responseMessageId] = responseMessage; if (stopResponseFlag) { controller.abort('User: Stop Response'); @@ -1373,7 +1367,7 @@ ); } - messages = messages; + history.messages[responseMessageId] = responseMessage; } if (autoScroll) { @@ -1414,7 +1408,7 @@ await saveChatHandler(_chatId); - messages = messages; + history.messages[responseMessageId] = responseMessage; stopResponseFlag = false; await tick(); @@ -1445,9 +1439,9 @@ scrollToBottom(); } + const messages = createMessagesList(responseMessageId); if (messages.length == 2 && selectedModels[0] === model.id) { window.history.replaceState(history.state, '', `/c/${_chatId}`); - const _title = await generateChatTitle(userPrompt); await setChatTitle(_chatId, _title); } @@ -1497,7 +1491,7 @@ ); } - messages = messages; + history.messages[responseMessageId] = responseMessage; }; const stopResponse = () => { @@ -1508,7 +1502,7 @@ const regenerateResponse = async (message) => { console.log('regenerateResponse'); - if (messages.length != 0) { + if (history.currentId) { let userMessage = history.messages[message.parentId]; let userPrompt = userMessage.content; @@ -1530,7 +1524,7 @@ console.log('continueGeneration'); const _chatId = JSON.parse(JSON.stringify($chatId)); - if (messages.length != 0 && messages.at(-1).done == true) { + if (history.currentId && history.messages[history.currentId].done == true) { const responseMessage = history.messages[history.currentId]; responseMessage.done = false; await tick(); @@ -1600,7 +1594,7 @@ description: $i18n.t('Generating search query') } ]; - messages = messages; + history.messages[responseMessageId] = responseMessage; const prompt = userMessage.content; let searchQuery = await generateSearchQuery( @@ -1620,7 +1614,7 @@ action: 'web_search', description: $i18n.t('No search query generated') }); - messages = messages; + history.messages[responseMessageId] = responseMessage; return; } @@ -1629,7 +1623,7 @@ action: 'web_search', description: $i18n.t(`Searching "{{searchQuery}}"`, { searchQuery }) }); - messages = messages; + history.messages[responseMessageId] = responseMessage; const results = await runWebSearch(localStorage.token, searchQuery).catch((error) => { console.log(error); @@ -1657,8 +1651,7 @@ type: 'web_search_results', urls: results.filenames }); - - messages = messages; + history.messages[responseMessageId] = responseMessage; } else { responseMessage.statusHistory.push({ done: true, @@ -1666,7 +1659,7 @@ action: 'web_search', description: 'No search results found' }); - messages = messages; + history.messages[responseMessageId] = responseMessage; } }; @@ -1680,9 +1673,8 @@ if ($chatId == _chatId) { if (!$temporaryChatEnabled) { chat = await updateChatById(localStorage.token, _chatId, { - messages: messages, - history: history, models: selectedModels, + history: history, params: params, files: chatFiles }); @@ -1700,7 +1692,7 @@ content: '' }; message.merged = mergedResponse; - messages = messages; + history.messages[messageId] = message; try { const [res, controller] = await generateMoACompletion( @@ -1722,7 +1714,7 @@ continue; } else { mergedResponse.content += value; - messages = messages; + history.messages[messageId] = message; } if (autoScroll) { @@ -1788,11 +1780,11 @@ /> {/if} - 0} {initNewChat} /> + - {#if $banners.length > 0 && messages.length === 0 && !$chatId && selectedModels.length <= 1} + {#if $banners.length > 0 && !history.currentId && !$chatId && selectedModels.length <= 1}
{#each $banners.filter( (b) => (b.dismissible ? !JSON.parse(localStorage.getItem('dismissedBannerIds') ?? '[]').includes(b.id) : true) ) as banner} @@ -1834,7 +1826,6 @@ bind:history bind:autoScroll bind:prompt - {messages} {selectedModels} {processing} {sendPrompt} @@ -1850,13 +1841,13 @@
{ const model = $models.find((m) => m.id === e); diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index ea4400bbc..c027b9158 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -61,15 +61,14 @@ let user = null; let chatInputPlaceholder = ''; - export let files = []; + export let history; + export let prompt = ''; + export let files = []; export let availableToolIds = []; export let selectedToolIds = []; export let webSearchEnabled = false; - export let prompt = ''; - export let messages = []; - let visionCapableModels = []; $: visionCapableModels = [...(atSelectedModel ? [atSelectedModel] : selectedModels)].filter( (model) => $models.find((m) => m.id === model)?.info?.meta?.capabilities?.vision ?? true @@ -272,7 +271,7 @@
- {#if autoScroll === false && messages.length > 0} + {#if autoScroll === false && !history?.currentId}
@@ -692,7 +691,7 @@ />
- {#if messages.length == 0 || messages.at(-1).done == true} + {#if !history?.currentId || history.messages[history.currentId].done == true}
- {#if messages.length == 0 || messages.at(-1).done == true} + {#if !history.currentId || history.messages[history.currentId].done == true} {#if prompt === ''}
diff --git a/src/lib/components/chat/Messages.svelte b/src/lib/components/chat/Messages.svelte index f9f4a63d2..7ea3a3d69 100644 --- a/src/lib/components/chat/Messages.svelte +++ b/src/lib/components/chat/Messages.svelte @@ -7,10 +7,8 @@ import { getChatList, updateChatById } from '$lib/apis/chats'; import { copyToClipboard, findWordIndices } from '$lib/utils'; - import UserMessage from './Messages/UserMessage.svelte'; - import ResponseMessage from './Messages/ResponseMessage.svelte'; import Placeholder from './Messages/Placeholder.svelte'; - import MultiResponseMessages from './Messages/MultiResponseMessages.svelte'; + import Message from './Messages/Message.svelte'; const i18n = getContext('i18n'); @@ -45,11 +43,14 @@ element.scrollTop = element.scrollHeight; }; - const copyToClipboardWithToast = async (text) => { - const res = await copyToClipboard(text); - if (res) { - toast.success($i18n.t('Copying to clipboard was successful!')); - } + const updateChatMessages = async () => { + await tick(); + await updateChatById(localStorage.token, chatId, { + history: history + }); + + currentChatPage.set(1); + await chats.set(await getChatList(localStorage.token, $currentChatPage)); }; const confirmEditMessage = async (messageId, content, submit = true) => { @@ -85,23 +86,11 @@ history.messages[messageId].content = content; await tick(); await updateChatById(localStorage.token, chatId, { - messages: messages, history: history }); } }; - const updateChatMessages = async () => { - await tick(); - await updateChatById(localStorage.token, chatId, { - messages: messages, - history: history - }); - - currentChatPage.set(1); - await chats.set(await getChatList(localStorage.token, $currentChatPage)); - }; - const confirmEditResponseMessage = async (messageId, content) => { history.messages[messageId].originalContent = history.messages[messageId].content; history.messages[messageId].content = content; @@ -243,7 +232,7 @@ } }; - const deleteMessageHandler = async (messageId) => { + const deleteMessage = async (messageId) => { const messageToDelete = history.messages[messageId]; const parentMessageId = messageToDelete.parentId; const childMessageIds = messageToDelete.childrenIds ?? []; @@ -279,14 +268,13 @@ // Update the chat await updateChatById(localStorage.token, chatId, { - messages: messages, history: history }); };
- {#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 2/6] 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 ba39f9bf56dfc09f357417c88256bbc77bd2dc0f Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Mon, 23 Sep 2024 17:40:24 +0200 Subject: [PATCH 4/6] refac --- src/lib/components/chat/MessageInput.svelte | 4 ++-- src/lib/components/chat/Messages.svelte | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index 099f1dcec..bb5250def 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -691,7 +691,7 @@ />
- {#if !history?.currentId || history.messages[history.currentId].done == true} + {#if !history?.currentId || history.messages[history.currentId]?.done == true}
- {#if !history.currentId || history.messages[history.currentId].done == true} + {#if !history.currentId || history.messages[history.currentId]?.done == true} {#if prompt === ''}
diff --git a/src/lib/components/chat/Messages.svelte b/src/lib/components/chat/Messages.svelte index 7e914ae9d..d159e80f9 100644 --- a/src/lib/components/chat/Messages.svelte +++ b/src/lib/components/chat/Messages.svelte @@ -337,9 +337,13 @@ messageId={message.id} idx={messageIdx} {user} + {showPreviousMessage} + {showNextMessage} {editMessage} {deleteMessage} {rateMessage} + {regenerateResponse} + {continueResponse} /> {/each}
From 84c1810b6efe99dc39781f4eed7ee66b5d1e3606 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Mon, 23 Sep 2024 23:20:27 +0200 Subject: [PATCH 5/6] refac --- src/lib/components/chat/Messages.svelte | 16 +- .../components/chat/Messages/Message.svelte | 84 ++--- .../Messages/MultiResponseMessages.svelte | 319 +++++++++--------- .../chat/Messages/ResponseMessage.svelte | 20 +- .../chat/Messages/UserMessage.svelte | 15 +- 5 files changed, 244 insertions(+), 210 deletions(-) diff --git a/src/lib/components/chat/Messages.svelte b/src/lib/components/chat/Messages.svelte index d159e80f9..5a6bc0112 100644 --- a/src/lib/components/chat/Messages.svelte +++ b/src/lib/components/chat/Messages.svelte @@ -333,7 +333,7 @@ {#each messages as message, messageIdx (message.id)} { + if (autoScroll) { + const element = document.getElementById('messages-container'); + autoScroll = + element.scrollHeight - element.scrollTop <= element.clientHeight + 50; + setTimeout(() => { + scrollToBottom(); + }, 100); + } + }} /> {/each}
diff --git a/src/lib/components/chat/Messages/Message.svelte b/src/lib/components/chat/Messages/Message.svelte index d60e17cc4..dd5c498a3 100644 --- a/src/lib/components/chat/Messages/Message.svelte +++ b/src/lib/components/chat/Messages/Message.svelte @@ -1,7 +1,8 @@ -
-
- {#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 6/6] 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 = {