Timothy J. Baek 6 kuukautta sitten
vanhempi
commit
02269a21a9

+ 28 - 31
src/lib/components/chat/Chat.svelte

@@ -1794,6 +1794,33 @@
 		console.log('stopResponse');
 	};
 
+	const submitMessage = async (parentId, prompt) => {
+		let userPrompt = prompt;
+		let userMessageId = uuidv4();
+
+		let userMessage = {
+			id: userMessageId,
+			parentId: parentId,
+			childrenIds: [],
+			role: 'user',
+			content: userPrompt,
+			models: selectedModels
+		};
+
+		if (parentId !== null) {
+			history.messages[parentId].childrenIds = [
+				...history.messages[parentId].childrenIds,
+				userMessageId
+			];
+		}
+
+		history.messages[userMessageId] = userMessage;
+		history.currentId = userMessageId;
+
+		await tick();
+		await sendPrompt(userPrompt, userMessageId);
+	};
+
 	const regenerateResponse = async (message) => {
 		console.log('regenerateResponse');
 
@@ -2204,42 +2231,12 @@
 									{selectedModels}
 									{sendPrompt}
 									{showMessage}
+									{submitMessage}
 									{continueResponse}
 									{regenerateResponse}
 									{mergeResponses}
 									{chatActionHandler}
 									bottomPadding={files.length > 0}
-									on:submit={async (e) => {
-										if (e.detail) {
-											// New user message
-											let userPrompt = e.detail.prompt;
-											let userMessageId = uuidv4();
-
-											let userMessage = {
-												id: userMessageId,
-												parentId: e.detail.parentId,
-												childrenIds: [],
-												role: 'user',
-												content: userPrompt,
-												models: selectedModels
-											};
-
-											let messageParentId = e.detail.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);
-										}
-									}}
 								/>
 							</div>
 						</div>

+ 33 - 31
src/lib/components/chat/Messages.svelte

@@ -29,8 +29,10 @@
 	export let continueResponse: Function;
 	export let regenerateResponse: Function;
 	export let mergeResponses: Function;
+
 	export let chatActionHandler: Function;
 	export let showMessage: Function = () => {};
+	export let submitMessage: Function = () => {};
 
 	export let readOnly = false;
 
@@ -79,9 +81,9 @@
 		element.scrollTop = element.scrollHeight;
 	};
 
-	const updateChatHistory = async () => {
-		await tick();
+	const updateChat = async () => {
 		history = history;
+		await tick();
 		await updateChatById(localStorage.token, chatId, {
 			history: history,
 			messages: messages
@@ -195,7 +197,7 @@
 			rating: rating
 		};
 
-		await updateChatHistory();
+		await updateChat();
 	};
 
 	const editMessage = async (messageId, content, submit = true) => {
@@ -232,7 +234,7 @@
 			} else {
 				// Edit user message
 				history.messages[messageId].content = content;
-				await updateChatHistory();
+				await updateChat();
 			}
 		} else {
 			if (submit) {
@@ -261,16 +263,25 @@
 					];
 				}
 
-				await updateChatHistory();
+				await updateChat();
 			} else {
 				// Edit response message
 				history.messages[messageId].originalContent = history.messages[messageId].content;
 				history.messages[messageId].content = content;
-				await updateChatHistory();
+				await updateChat();
 			}
 		}
 	};
 
+	const actionMessage = async (actionId, event = null) => {
+		await chatActionHandler(chatId, actionId, message.model, message.id, event);
+	};
+
+	const saveMessage = async (messageId, message) => {
+		history.messages[messageId] = message;
+		await updateChat();
+	};
+
 	const deleteMessage = async (messageId) => {
 		const messageToDelete = history.messages[messageId];
 		const parentMessageId = messageToDelete.parentId;
@@ -306,7 +317,17 @@
 		showMessage({ id: parentMessageId });
 
 		// Update the chat
-		await updateChatHistory();
+		await updateChat();
+	};
+
+	const triggerScroll = () => {
+		if (autoScroll) {
+			const element = document.getElementById('messages-container');
+			autoScroll = element.scrollHeight - element.scrollTop <= element.clientHeight + 50;
+			setTimeout(() => {
+				scrollToBottom();
+			}, 100);
+		}
 	};
 </script>
 
@@ -372,37 +393,18 @@
 							{user}
 							{showPreviousMessage}
 							{showNextMessage}
+							{updateChat}
 							{editMessage}
 							{deleteMessage}
 							{rateMessage}
+							{actionMessage}
+							{saveMessage}
+							{submitMessage}
 							{regenerateResponse}
 							{continueResponse}
 							{mergeResponses}
+							{triggerScroll}
 							{readOnly}
-							on:submit={async (e) => {
-								dispatch('submit', e.detail);
-							}}
-							on:action={async (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:update={() => {
-								updateChatHistory();
-							}}
-							on:scroll={() => {
-								if (autoScroll) {
-									const element = document.getElementById('messages-container');
-									autoScroll =
-										element.scrollHeight - element.scrollTop <= element.clientHeight + 50;
-									setTimeout(() => {
-										scrollToBottom();
-									}, 100);
-								}
-							}}
 						/>
 					{/each}
 				</div>

+ 16 - 53
src/lib/components/chat/Messages/Message.svelte

@@ -22,23 +22,21 @@
 
 	export let showPreviousMessage;
 	export let showNextMessage;
+	export let updateChat;
 
 	export let editMessage;
+	export let saveMessage;
 	export let deleteMessage;
 	export let rateMessage;
+	export let actionMessage;
+	export let submitMessage;
 
 	export let regenerateResponse;
 	export let continueResponse;
-
-	// MultiResponseMessages
 	export let mergeResponses;
 
-	export let autoScroll = false;
+	export let triggerScroll;
 	export let readOnly = false;
-
-	onMount(() => {
-		// console.log('message', idx);
-	});
 </script>
 
 <div
@@ -61,7 +59,7 @@
 				{showPreviousMessage}
 				{showNextMessage}
 				{editMessage}
-				on:delete={() => deleteMessage(messageId)}
+				{deleteMessage}
 				{readOnly}
 			/>
 		{:else if (history.messages[history.messages[messageId].parentId]?.models?.length ?? 1) === 1}
@@ -73,30 +71,14 @@
 				siblings={history.messages[history.messages[messageId].parentId]?.childrenIds ?? []}
 				{showPreviousMessage}
 				{showNextMessage}
+				{updateChat}
 				{editMessage}
+				{saveMessage}
 				{rateMessage}
+				{actionMessage}
+				{submitMessage}
 				{continueResponse}
 				{regenerateResponse}
-				on:submit={async (e) => {
-					dispatch('submit', e.detail);
-				}}
-				on:action={async (e) => {
-					dispatch('action', e.detail);
-				}}
-				on:update={async (e) => {
-					dispatch('update');
-				}}
-				on:save={async (e) => {
-					console.log('save', e);
-
-					const message = e.detail;
-					if (message) {
-						history.messages[message.id] = message;
-						dispatch('update');
-					} else {
-						dispatch('update');
-					}
-				}}
 				{readOnly}
 			/>
 		{:else}
@@ -105,35 +87,16 @@
 				{chatId}
 				{messageId}
 				isLastMessage={messageId === history?.currentId}
-				{rateMessage}
+				{updateChat}
 				{editMessage}
+				{saveMessage}
+				{rateMessage}
+				{actionMessage}
+				{submitMessage}
 				{continueResponse}
 				{regenerateResponse}
 				{mergeResponses}
-				on:submit={async (e) => {
-					dispatch('submit', e.detail);
-				}}
-				on:action={async (e) => {
-					dispatch('action', e.detail);
-				}}
-				on:update={async (e) => {
-					dispatch('update');
-				}}
-				on:save={async (e) => {
-					console.log('save', e);
-					const message = e.detail;
-					if (message) {
-						history.messages[message.id] = message;
-						dispatch('update');
-					} else {
-						dispatch('update');
-					}
-				}}
-				on:change={async () => {
-					await tick();
-					dispatch('update');
-					dispatch('scroll');
-				}}
+				{triggerScroll}
 				{readOnly}
 			/>
 		{/if}

+ 26 - 19
src/lib/components/chat/Messages/MultiResponseMessages.svelte

@@ -25,13 +25,19 @@
 	export let isLastMessage;
 	export let readOnly = false;
 
+	export let updateChat: Function;
 	export let editMessage: Function;
+	export let saveMessage: Function;
 	export let rateMessage: Function;
+	export let actionMessage: Function;
 
+	export let submitMessage: Function;
 	export let continueResponse: Function;
 	export let regenerateResponse: Function;
 	export let mergeResponses: Function;
 
+	export let triggerScroll: Function;
+
 	const dispatch = createEventDispatcher();
 
 	let currentMessageId;
@@ -46,7 +52,7 @@
 		}
 	}
 
-	const showPreviousMessage = (modelIdx) => {
+	const showPreviousMessage = async (modelIdx) => {
 		groupedMessageIdsIdx[modelIdx] = Math.max(0, groupedMessageIdsIdx[modelIdx] - 1);
 
 		let messageId = groupedMessageIds[modelIdx].messageIds[groupedMessageIdsIdx[modelIdx]];
@@ -60,10 +66,13 @@
 		}
 
 		history.currentId = messageId;
-		dispatch('change');
+
+		await tick();
+		await updateChat();
+		triggerScroll();
 	};
 
-	const showNextMessage = (modelIdx) => {
+	const showNextMessage = async (modelIdx) => {
 		groupedMessageIdsIdx[modelIdx] = Math.min(
 			groupedMessageIds[modelIdx].messageIds.length - 1,
 			groupedMessageIdsIdx[modelIdx] + 1
@@ -80,7 +89,10 @@
 		}
 
 		history.currentId = messageId;
-		dispatch('change');
+
+		await tick();
+		await updateChat();
+		triggerScroll();
 	};
 
 	const initHandler = async () => {
@@ -182,7 +194,7 @@
 							: `border-gray-50 dark:border-gray-850 border-dashed ${
 									$mobile ? 'min-w-full' : 'min-w-80'
 								}`} transition-all p-5 rounded-2xl"
-						on:click={() => {
+						on:click={async () => {
 							if (messageId != _messageId) {
 								let currentMessageId = _messageId;
 								let messageChildrenIds = history.messages[currentMessageId].childrenIds;
@@ -191,7 +203,10 @@
 									messageChildrenIds = history.messages[currentMessageId].childrenIds;
 								}
 								history.currentId = currentMessageId;
-								dispatch('change');
+
+								await tick();
+								await updateChat();
+								triggerScroll();
 							}
 						}}
 					>
@@ -205,8 +220,12 @@
 									siblings={groupedMessageIds[modelIdx].messageIds}
 									showPreviousMessage={() => showPreviousMessage(modelIdx)}
 									showNextMessage={() => showNextMessage(modelIdx)}
-									{rateMessage}
+									{updateChat}
 									{editMessage}
+									{saveMessage}
+									{rateMessage}
+									{actionMessage}
+									{submitMessage}
 									{continueResponse}
 									regenerateResponse={async (message) => {
 										regenerateResponse(message);
@@ -214,18 +233,6 @@
 										groupedMessageIdsIdx[modelIdx] =
 											groupedMessageIds[modelIdx].messageIds.length - 1;
 									}}
-									on:submit={async (e) => {
-										dispatch('submit', e.detail);
-									}}
-									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}

+ 58 - 116
src/lib/components/chat/Messages/ResponseMessage.svelte

@@ -15,9 +15,6 @@
 	import {
 		copyToClipboard as _copyToClipboard,
 		approximateToHumanReadable,
-		extractParagraphsForAudio,
-		extractSentencesForAudio,
-		cleanText,
 		getMessageContentParts,
 		sanitizeResponseContent,
 		createMessagesList
@@ -33,7 +30,6 @@
 	import Spinner from '$lib/components/common/Spinner.svelte';
 	import WebSearchResults from './ResponseMessage/WebSearchResults.svelte';
 	import Sparkles from '$lib/components/icons/Sparkles.svelte';
-	import Markdown from './Markdown.svelte';
 	import Error from './Error.svelte';
 	import Citations from './Citations.svelte';
 	import CodeExecutions from './CodeExecutions.svelte';
@@ -112,9 +108,13 @@
 	export let showPreviousMessage: Function;
 	export let showNextMessage: Function;
 
+	export let updateChat: Function;
 	export let editMessage: Function;
+	export let saveMessage: Function;
 	export let rateMessage: Function;
+	export let actionMessage: Function;
 
+	export let submitMessage: Function;
 	export let continueResponse: Function;
 	export let regenerateResponse: Function;
 
@@ -329,7 +329,10 @@
 				url: `${image.url}`
 			}));
 
-			dispatch('save', { ...message, files: files });
+			saveMessage(message.id, {
+				...message,
+				files: files
+			});
 		}
 
 		generatingImage = false;
@@ -422,7 +425,7 @@
 		}
 
 		console.log(updatedMessage);
-		dispatch('save', updatedMessage);
+		saveMessage(message.id, updatedMessage);
 
 		await tick();
 
@@ -443,7 +446,7 @@
 					updatedMessage.annotation.tags = tags;
 					feedbackItem.data.tags = tags;
 
-					dispatch('save', updatedMessage);
+					saveMessage(message.id, updatedMessage);
 					await updateFeedbackById(
 						localStorage.token,
 						updatedMessage.feedbackId,
@@ -631,22 +634,19 @@
 												message.id
 											].content.replace(raw, raw.replace(oldContent, newContent));
 
-											dispatch('update');
+											updateChat();
 										}}
 										on:select={(e) => {
 											const { type, content } = e.detail;
 
 											if (type === 'explain') {
-												dispatch('submit', {
-													parentId: message.id,
-													prompt: `Explain this section to me in more detail\n\n\`\`\`\n${content}\n\`\`\``
-												});
+												submitMessage(
+													message.id,
+													`Explain this section to me in more detail\n\n\`\`\`\n${content}\n\`\`\``
+												);
 											} else if (type === 'ask') {
 												const input = e.detail?.input ?? '';
-												dispatch('submit', {
-													parentId: message.id,
-													prompt: `\`\`\`\n${content}\n\`\`\`\n${input}`
-												});
+												submitMessage(message.id, `\`\`\`\n${content}\n\`\`\`\n${input}`);
 											}
 										}}
 									/>
@@ -1019,21 +1019,6 @@
 												disabled={feedbackLoading}
 												on:click={async () => {
 													await feedbackHandler(1);
-
-													(model?.actions ?? [])
-														.filter((action) => action?.__webui__ ?? false)
-														.forEach((action) => {
-															dispatch('action', {
-																id: action.id,
-																event: {
-																	id: 'good-response',
-																	data: {
-																		messageId: message.id
-																	}
-																}
-															});
-														});
-
 													window.setTimeout(() => {
 														document
 															.getElementById(`message-feedback-${message.id}`)
@@ -1070,21 +1055,6 @@
 												disabled={feedbackLoading}
 												on:click={async () => {
 													await feedbackHandler(-1);
-
-													(model?.actions ?? [])
-														.filter((action) => action?.__webui__ ?? false)
-														.forEach((action) => {
-															dispatch('action', {
-																id: action.id,
-																event: {
-																	id: 'bad-response',
-																	data: {
-																		messageId: message.id
-																	}
-																}
-															});
-														});
-
 													window.setTimeout(() => {
 														document
 															.getElementById(`message-feedback-${message.id}`)
@@ -1120,20 +1090,6 @@
 													: '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={() => {
 													continueResponse();
-
-													(model?.actions ?? [])
-														.filter((action) => action?.__webui__ ?? false)
-														.forEach((action) => {
-															dispatch('action', {
-																id: action.id,
-																event: {
-																	id: 'continue-response',
-																	data: {
-																		messageId: message.id
-																	}
-																}
-															});
-														});
 												}}
 											>
 												<svg
@@ -1157,50 +1113,52 @@
 												</svg>
 											</button>
 										</Tooltip>
+									{/if}
 
-										<Tooltip content={$i18n.t('Regenerate')} placement="bottom">
-											<button
-												type="button"
-												class="{isLastMessage
-													? '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={() => {
-													showRateComment = false;
-													regenerateResponse(message);
-
-													(model?.actions ?? [])
-														.filter((action) => action?.__webui__ ?? false)
-														.forEach((action) => {
-															dispatch('action', {
-																id: action.id,
-																event: {
-																	id: 'regenerate-response',
-																	data: {
-																		messageId: message.id
-																	}
+									<Tooltip content={$i18n.t('Regenerate')} placement="bottom">
+										<button
+											type="button"
+											class="{isLastMessage
+												? '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={() => {
+												showRateComment = false;
+												regenerateResponse(message);
+
+												(model?.actions ?? [])
+													.filter((action) => action?.__webui__ ?? false)
+													.forEach((action) => {
+														dispatch('action', {
+															id: action.id,
+															event: {
+																id: 'regenerate-response',
+																data: {
+																	messageId: message.id
 																}
-															});
+															}
 														});
-												}}
+													});
+											}}
+										>
+											<svg
+												xmlns="http://www.w3.org/2000/svg"
+												fill="none"
+												viewBox="0 0 24 24"
+												stroke-width="2.3"
+												stroke="currentColor"
+												class="w-4 h-4"
 											>
-												<svg
-													xmlns="http://www.w3.org/2000/svg"
-													fill="none"
-													viewBox="0 0 24 24"
-													stroke-width="2.3"
-													stroke="currentColor"
-													class="w-4 h-4"
-												>
-													<path
-														stroke-linecap="round"
-														stroke-linejoin="round"
-														d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99"
-													/>
-												</svg>
-											</button>
-										</Tooltip>
+												<path
+													stroke-linecap="round"
+													stroke-linejoin="round"
+													d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99"
+												/>
+											</svg>
+										</button>
+									</Tooltip>
 
-										{#each (model?.actions ?? []).filter((action) => !(action?.__webui__ ?? false)) as action}
+									{#if isLastMessage}
+										{#each model?.actions ?? [] as action}
 											<Tooltip content={action.name} placement="bottom">
 												<button
 													type="button"
@@ -1208,7 +1166,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={() => {
-														dispatch('action', action.id);
+														actionMessage(action.id);
 													}}
 												>
 													{#if action.icon_url}
@@ -1242,22 +1200,6 @@
 									comment: e.detail.comment,
 									reason: e.detail.reason
 								});
-
-								(model?.actions ?? [])
-									.filter((action) => action?.__webui__ ?? false)
-									.forEach((action) => {
-										dispatch('action', {
-											id: action.id,
-											event: {
-												id: 'rate-comment',
-												data: {
-													messageId: message.id,
-													comment: e.detail.comment,
-													reason: e.detail.reason
-												}
-											}
-										});
-									});
 							}}
 						/>
 					{/if}

+ 3 - 3
src/lib/components/chat/Messages/UserMessage.svelte

@@ -1,7 +1,7 @@
 <script lang="ts">
 	import dayjs from 'dayjs';
 	import { toast } from 'svelte-sonner';
-	import { tick, createEventDispatcher, getContext, onMount } from 'svelte';
+	import { tick, getContext, onMount } from 'svelte';
 
 	import { models, settings } from '$lib/stores';
 	import { user as _user } from '$lib/stores';
@@ -19,7 +19,6 @@
 
 	const i18n = getContext('i18n');
 
-	const dispatch = createEventDispatcher();
 	export let user;
 
 	export let history;
@@ -31,6 +30,7 @@
 	export let showNextMessage: Function;
 
 	export let editMessage: Function;
+	export let deleteMessage: Function;
 
 	export let isFirstMessage: boolean;
 	export let readOnly: boolean;
@@ -78,7 +78,7 @@
 	};
 
 	const deleteMessageHandler = async () => {
-		dispatch('delete', message.id);
+		deleteMessage(message.id);
 	};
 
 	onMount(() => {