diff --git a/src/lib/components/chat/Messages/MultiResponseMessages.svelte b/src/lib/components/chat/Messages/MultiResponseMessages.svelte index 3b3dd9b194..c2c6e9fd1e 100644 --- a/src/lib/components/chat/Messages/MultiResponseMessages.svelte +++ b/src/lib/components/chat/Messages/MultiResponseMessages.svelte @@ -3,7 +3,7 @@ import { onMount, tick, getContext } from 'svelte'; import { createEventDispatcher } from 'svelte'; - import { mobile, settings } from '$lib/stores'; + import { mobile, models, settings } from '$lib/stores'; import { generateMoACompletion } from '$lib/apis'; import { updateChatById } from '$lib/apis/chats'; @@ -17,6 +17,8 @@ import Name from './Name.svelte'; import Skeleton from './Skeleton.svelte'; import localizedFormat from 'dayjs/plugin/localizedFormat'; + import ProfileImage from './ProfileImage.svelte'; + import { WEBUI_BASE_URL } from '$lib/constants'; const i18n = getContext('i18n'); dayjs.extend(localizedFormat); @@ -53,6 +55,8 @@ let groupedMessageIds = {}; let groupedMessageIdsIdx = {}; + let selectedModelIdx = null; + let message = JSON.parse(JSON.stringify(history.messages[messageId])); $: if (history.messages) { if (JSON.stringify(message) !== JSON.stringify(history.messages[messageId])) { @@ -183,11 +187,30 @@ } }, {}); + selectedModelIdx = history.messages[messageId]?.modelIdx; + console.log(groupedMessageIds, groupedMessageIdsIdx); await tick(); }; + const onGroupClick = async (_messageId, modelIdx) => { + if (messageId != _messageId) { + let currentMessageId = _messageId; + let messageChildrenIds = history.messages[currentMessageId].childrenIds; + while (messageChildrenIds.length !== 0) { + currentMessageId = messageChildrenIds.at(-1); + messageChildrenIds = history.messages[currentMessageId].childrenIds; + } + history.currentId = currentMessageId; + selectedModelIdx = modelIdx; + + // await tick(); + // await updateChat(); + // triggerScroll(); + } + }; + const mergeResponsesHandler = async () => { const responses = Object.keys(groupedMessageIds).map((modelIdx) => { const { messageIds } = groupedMessageIds[modelIdx]; @@ -217,37 +240,58 @@ class="flex snap-x snap-mandatory overflow-x-auto scrollbar-hidden" id="responses-container-{chatId}-{parentMessage.id}" > - {#each Object.keys(groupedMessageIds) as modelIdx} - {#if groupedMessageIdsIdx[modelIdx] !== undefined && groupedMessageIds[modelIdx].messageIds.length > 0} - - - {@const _messageId = - groupedMessageIds[modelIdx].messageIds[groupedMessageIdsIdx[modelIdx]]} + {#if $settings?.displayMultiModelResponsesInTabs ?? false} +
+
+
+ {#each Object.keys(groupedMessageIds) as modelIdx} + {#if groupedMessageIdsIdx[modelIdx] !== undefined && groupedMessageIds[modelIdx].messageIds.length > 0} + + -
{ - if (messageId != _messageId) { - let currentMessageId = _messageId; - let messageChildrenIds = history.messages[currentMessageId].childrenIds; - while (messageChildrenIds.length !== 0) { - currentMessageId = messageChildrenIds.at(-1); - messageChildrenIds = history.messages[currentMessageId].childrenIds; - } - history.currentId = currentMessageId; - // await tick(); - // await updateChat(); - // triggerScroll(); - } - }} - > + {@const _messageId = + groupedMessageIds[modelIdx].messageIds[groupedMessageIdsIdx[modelIdx]]} + + {@const model = $models.find((m) => m.id === history.messages[_messageId]?.model)} + + + {/if} + {/each} +
+
+ + {#if selectedModelIdx !== null} + {@const _messageId = + groupedMessageIds[selectedModelIdx].messageIds[ + groupedMessageIdsIdx[selectedModelIdx] + ]} {#key history.currentId} {#if message} gotoMessage(modelIdx, messageIdx)} - showPreviousMessage={() => showPreviousMessage(modelIdx)} - showNextMessage={() => showNextMessage(modelIdx)} + siblings={groupedMessageIds[selectedModelIdx].messageIds} + gotoMessage={(message, messageIdx) => gotoMessage(selectedModelIdx, messageIdx)} + showPreviousMessage={() => showPreviousMessage(selectedModelIdx)} + showNextMessage={() => showNextMessage(selectedModelIdx)} {setInputText} {updateChat} {editMessage} @@ -272,17 +316,73 @@ regenerateResponse={async (message) => { regenerateResponse(message); await tick(); - groupedMessageIdsIdx[modelIdx] = - groupedMessageIds[modelIdx].messageIds.length - 1; + groupedMessageIdsIdx[selectedModelIdx] = + groupedMessageIds[selectedModelIdx].messageIds.length - 1; }} {addMessages} {readOnly} /> {/if} {/key} -
- {/if} - {/each} + {/if} +
+ {:else} + {#each Object.keys(groupedMessageIds) as modelIdx} + {#if groupedMessageIdsIdx[modelIdx] !== undefined && groupedMessageIds[modelIdx].messageIds.length > 0} + + + {@const _messageId = + groupedMessageIds[modelIdx].messageIds[groupedMessageIdsIdx[modelIdx]]} + +
{ + onGroupClick(_messageId, modelIdx); + }} + > + {#key history.currentId} + {#if message} + gotoMessage(modelIdx, messageIdx)} + showPreviousMessage={() => showPreviousMessage(modelIdx)} + showNextMessage={() => showNextMessage(modelIdx)} + {setInputText} + {updateChat} + {editMessage} + {saveMessage} + {rateMessage} + {deleteMessage} + {actionMessage} + {submitMessage} + {continueResponse} + regenerateResponse={async (message) => { + regenerateResponse(message); + await tick(); + groupedMessageIdsIdx[modelIdx] = + groupedMessageIds[modelIdx].messageIds.length - 1; + }} + {addMessages} + {readOnly} + /> + {/if} + {/key} +
+ {/if} + {/each} + {/if} {#if !readOnly} @@ -296,7 +396,7 @@ {#if history.messages[messageId]?.merged?.status} {@const message = history.messages[messageId]?.merged} -
+
{$i18n.t('Merged Response')} diff --git a/src/lib/components/chat/Settings/Interface.svelte b/src/lib/components/chat/Settings/Interface.svelte index b0c7b89ee6..fb260f7672 100644 --- a/src/lib/components/chat/Settings/Interface.svelte +++ b/src/lib/components/chat/Settings/Interface.svelte @@ -36,6 +36,7 @@ let highContrastMode = false; let detectArtifacts = true; + let displayMultiModelResponsesInTabs = false; let richTextInput = true; let showFormattingToolbar = false; @@ -155,6 +156,11 @@ saveSettings({ showEmojiInCall: showEmojiInCall }); }; + const toggleDisplayMultiModelResponsesInTabs = async () => { + displayMultiModelResponsesInTabs = !displayMultiModelResponsesInTabs; + saveSettings({ displayMultiModelResponsesInTabs }); + }; + const toggleVoiceInterruption = async () => { voiceInterruption = !voiceInterruption; saveSettings({ voiceInterruption: voiceInterruption }); @@ -344,6 +350,7 @@ showEmojiInCall = $settings?.showEmojiInCall ?? false; voiceInterruption = $settings?.voiceInterruption ?? false; + displayMultiModelResponsesInTabs = $settings?.displayMultiModelResponsesInTabs ?? false; chatFadeStreamingText = $settings?.chatFadeStreamingText ?? true; richTextInput = $settings?.richTextInput ?? true; @@ -853,6 +860,29 @@
+
+
+
+ {$i18n.t('Display Multi-model Responses in Tabs')} +
+ + +
+
+