|
@@ -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}
|
|
|
- <!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
|
- <!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
|
- {@const _messageId =
|
|
|
- groupedMessageIds[modelIdx].messageIds[groupedMessageIdsIdx[modelIdx]]}
|
|
|
-
|
|
|
- <div
|
|
|
- class=" snap-center w-full max-w-full m-1 border {history.messages[messageId]
|
|
|
- ?.modelIdx == modelIdx
|
|
|
- ? `bg-gray-50 dark:bg-gray-850 border-gray-100 dark:border-gray-800 border-2 ${
|
|
|
- $mobile ? 'min-w-full' : 'min-w-80'
|
|
|
- }`
|
|
|
- : `border-gray-100 dark:border-gray-850 border-dashed ${
|
|
|
- $mobile ? 'min-w-full' : 'min-w-80'
|
|
|
- }`} transition-all p-5 rounded-2xl"
|
|
|
- on:click={async () => {
|
|
|
- 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();
|
|
|
- }
|
|
|
- }}
|
|
|
- >
|
|
|
+ {#if $settings?.displayMultiModelResponsesInTabs ?? false}
|
|
|
+ <div class="w-full">
|
|
|
+ <div class=" flex w-full mb-4 border-b border-gray-200 dark:border-gray-850">
|
|
|
+ <div
|
|
|
+ class="flex gap-2 scrollbar-none overflow-x-auto w-fit text-center font-medium bg-transparent pt-1 text-sm"
|
|
|
+ >
|
|
|
+ {#each Object.keys(groupedMessageIds) as modelIdx}
|
|
|
+ {#if groupedMessageIdsIdx[modelIdx] !== undefined && groupedMessageIds[modelIdx].messageIds.length > 0}
|
|
|
+ <!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
|
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
|
+
|
|
|
+ {@const _messageId =
|
|
|
+ groupedMessageIds[modelIdx].messageIds[groupedMessageIdsIdx[modelIdx]]}
|
|
|
+
|
|
|
+ {@const model = $models.find((m) => m.id === history.messages[_messageId]?.model)}
|
|
|
+
|
|
|
+ <button
|
|
|
+ class="min-w-fit {selectedModelIdx == modelIdx
|
|
|
+ ? ' dark:border-gray-300 '
|
|
|
+ : ' opacity-35 border-transparent'} pb-1.5 px-2.5 transition border-b-2"
|
|
|
+ on:click={async () => {
|
|
|
+ if (selectedModelIdx != modelIdx) {
|
|
|
+ selectedModelIdx = modelIdx;
|
|
|
+ }
|
|
|
+
|
|
|
+ onGroupClick(_messageId, modelIdx);
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <div class="flex items-center gap-1.5">
|
|
|
+ <!-- <ProfileImage
|
|
|
+ src={model?.info?.meta?.profile_image_url ??
|
|
|
+ ($i18n.language === 'dg-DG'
|
|
|
+ ? `${WEBUI_BASE_URL}/doge.png`
|
|
|
+ : `${WEBUI_BASE_URL}/favicon.png`)}
|
|
|
+ className={'size-5 assistant-message-profile-image'}
|
|
|
+ /> -->
|
|
|
+
|
|
|
+ <div class="-translate-y-[1px]">
|
|
|
+ {model ? `${model.name}` : history.messages[_messageId]?.model}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </button>
|
|
|
+ {/if}
|
|
|
+ {/each}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {#if selectedModelIdx !== null}
|
|
|
+ {@const _messageId =
|
|
|
+ groupedMessageIds[selectedModelIdx].messageIds[
|
|
|
+ groupedMessageIdsIdx[selectedModelIdx]
|
|
|
+ ]}
|
|
|
{#key history.currentId}
|
|
|
{#if message}
|
|
|
<ResponseMessage
|
|
@@ -256,10 +300,10 @@
|
|
|
messageId={_messageId}
|
|
|
{selectedModels}
|
|
|
isLastMessage={true}
|
|
|
- siblings={groupedMessageIds[modelIdx].messageIds}
|
|
|
- gotoMessage={(message, messageIdx) => 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}
|
|
|
- </div>
|
|
|
- {/if}
|
|
|
- {/each}
|
|
|
+ {/if}
|
|
|
+ </div>
|
|
|
+ {:else}
|
|
|
+ {#each Object.keys(groupedMessageIds) as modelIdx}
|
|
|
+ {#if groupedMessageIdsIdx[modelIdx] !== undefined && groupedMessageIds[modelIdx].messageIds.length > 0}
|
|
|
+ <!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
|
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
|
+ {@const _messageId =
|
|
|
+ groupedMessageIds[modelIdx].messageIds[groupedMessageIdsIdx[modelIdx]]}
|
|
|
+
|
|
|
+ <div
|
|
|
+ class=" snap-center w-full max-w-full m-1 border {history.messages[messageId]
|
|
|
+ ?.modelIdx == modelIdx
|
|
|
+ ? `bg-gray-50 dark:bg-gray-850 border-gray-100 dark:border-gray-800 border-2 ${
|
|
|
+ $mobile ? 'min-w-full' : 'min-w-80'
|
|
|
+ }`
|
|
|
+ : `border-gray-100 dark:border-gray-850 border-dashed ${
|
|
|
+ $mobile ? 'min-w-full' : 'min-w-80'
|
|
|
+ }`} transition-all p-5 rounded-2xl"
|
|
|
+ on:click={async () => {
|
|
|
+ onGroupClick(_messageId, modelIdx);
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {#key history.currentId}
|
|
|
+ {#if message}
|
|
|
+ <ResponseMessage
|
|
|
+ {chatId}
|
|
|
+ {history}
|
|
|
+ messageId={_messageId}
|
|
|
+ {selectedModels}
|
|
|
+ isLastMessage={true}
|
|
|
+ siblings={groupedMessageIds[modelIdx].messageIds}
|
|
|
+ gotoMessage={(message, messageIdx) => 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}
|
|
|
+ </div>
|
|
|
+ {/if}
|
|
|
+ {/each}
|
|
|
+ {/if}
|
|
|
</div>
|
|
|
|
|
|
{#if !readOnly}
|
|
@@ -296,7 +396,7 @@
|
|
|
{#if history.messages[messageId]?.merged?.status}
|
|
|
{@const message = history.messages[messageId]?.merged}
|
|
|
|
|
|
- <div class="w-full rounded-xl pl-5 pr-2 py-2">
|
|
|
+ <div class="w-full rounded-xl pl-5 pr-2 py-2 mt-2">
|
|
|
<Name>
|
|
|
{$i18n.t('Merged Response')}
|
|
|
|