浏览代码

enh: add to conversation

Timothy Jaeryang Baek 4 月之前
父节点
当前提交
47318daef0

+ 65 - 0
src/lib/components/chat/Chat.svelte

@@ -985,6 +985,70 @@
 		}
 	};
 
+	const addMessages = async ({ modelId, messages }) => {
+		const model = $models.filter((m) => m.id === modelId).at(0);
+		const messageList = createMessagesList(history.currentId);
+
+		let parentMessage = messageList.length !== 0 ? messageList.at(-1) : null;
+		let parentId = parentMessage ? parentMessage.id : null;
+		for (const message of messages) {
+			let messageId = uuidv4();
+
+			if (message.role === 'user') {
+				const userMessage = {
+					id: messageId,
+					parentId: parentId,
+					childrenIds: [],
+					timestamp: Math.floor(Date.now() / 1000),
+					...message
+				};
+
+				if (parentMessage) {
+					parentMessage.childrenIds.push(messageId);
+					history.messages[parentMessage.id] = parentMessage;
+				}
+
+				history.messages[messageId] = userMessage;
+				parentMessage = userMessage;
+				parentId = messageId;
+			} else {
+				const responseMessage = {
+					id: messageId,
+					parentId: parentId,
+					childrenIds: [],
+					done: true,
+					model: model.id,
+					modelName: model.name ?? model.id,
+					modelIdx: 0,
+					timestamp: Math.floor(Date.now() / 1000),
+					...message
+				};
+
+				if (parentMessage) {
+					parentMessage.childrenIds.push(messageId);
+					history.messages[parentMessage.id] = parentMessage;
+				}
+
+				history.messages[messageId] = responseMessage;
+				parentMessage = responseMessage;
+				parentId = messageId;
+			}
+		}
+
+		history.currentId = parentId;
+		await tick();
+
+		if (autoScroll) {
+			scrollToBottom();
+		}
+
+		if (messages.length === 0) {
+			await initChatHandler();
+		} else {
+			await saveChatHandler($chatId);
+		}
+	};
+
 	const chatCompletionEventHandler = async (data, message, chatId) => {
 		const { id, done, choices, sources, selectedModelId, error, usage } = data;
 
@@ -1937,6 +2001,7 @@
 									{regenerateResponse}
 									{mergeResponses}
 									{chatActionHandler}
+									{addMessages}
 									bottomPadding={files.length > 0}
 								/>
 							</div>

+ 20 - 4
src/lib/components/chat/ContentRenderer/FloatingButtons.svelte

@@ -26,6 +26,7 @@
 
 	let prompt = '';
 	let responseContent = null;
+	let responseDone = false;
 
 	const askHandler = async () => {
 		if (!model) {
@@ -69,6 +70,7 @@
 					for (const line of lines) {
 						if (line.startsWith('data: ')) {
 							if (line.startsWith('data: [DONE]')) {
+								responseDone = true;
 								continue;
 							} else {
 								// Parse the JSON chunk
@@ -145,6 +147,7 @@
 					for (const line of lines) {
 						if (line.startsWith('data: ')) {
 							if (line.startsWith('data: [DONE]')) {
+								responseDone = true;
 								continue;
 							} else {
 								// Parse the JSON chunk
@@ -181,7 +184,7 @@
 	};
 
 	const addHandler = async () => {
-		newMessages = [
+		const messages = [
 			{
 				role: 'user',
 				content: prompt
@@ -192,13 +195,15 @@
 			}
 		];
 
-		responseContent = null;
-
-		onAdd();
+		onAdd({
+			modelId: model,
+			messages: messages
+		});
 	};
 
 	export const closeHandler = () => {
 		responseContent = null;
+		responseDone = false;
 		floatingInput = false;
 		floatingInputValue = '';
 	};
@@ -306,6 +311,17 @@
 					{:else}
 						<Markdown id={`${id}-float-response`} content={responseContent} />
 					{/if}
+
+					{#if responseDone}
+						<div class="flex justify-end pt-3 text-sm font-medium">
+							<button
+								class="px-3.5 py-1.5 text-sm font-medium bg-black hover:bg-gray-900 text-white dark:bg-white dark:text-black dark:hover:bg-gray-100 transition rounded-full"
+								on:click={addHandler}
+							>
+								{$i18n.t('Add')}
+							</button>
+						</div>
+					{/if}
 				</div>
 			</div>
 		</div>

+ 2 - 0
src/lib/components/chat/Messages.svelte

@@ -33,6 +33,7 @@
 	export let chatActionHandler: Function;
 	export let showMessage: Function = () => {};
 	export let submitMessage: Function = () => {};
+	export let addMessages: Function = () => {};
 
 	export let readOnly = false;
 
@@ -404,6 +405,7 @@
 							{regenerateResponse}
 							{continueResponse}
 							{mergeResponses}
+							{addMessages}
 							{triggerScroll}
 							{readOnly}
 						/>

+ 5 - 1
src/lib/components/chat/Messages/ContentRenderer.svelte

@@ -16,7 +16,9 @@
 
 	export let save = false;
 	export let floatingButtons = true;
+
 	export let onSourceClick = () => {};
+	export let onAddMessages = () => {};
 
 	let contentContainerElement;
 
@@ -163,7 +165,9 @@
 		{id}
 		model={model?.id}
 		messages={createMessagesList(history, id)}
-		onSave={() => {
+		onAdd={({ modelId, messages }) => {
+			console.log(modelId, messages);
+			onAddMessages({ modelId, messages });
 			closeFloatingButtons();
 		}}
 	/>

+ 3 - 0
src/lib/components/chat/Messages/Message.svelte

@@ -35,6 +35,7 @@
 	export let continueResponse;
 	export let mergeResponses;
 
+	export let addMessages;
 	export let triggerScroll;
 	export let readOnly = false;
 </script>
@@ -79,6 +80,7 @@
 				{submitMessage}
 				{continueResponse}
 				{regenerateResponse}
+				{addMessages}
 				{readOnly}
 			/>
 		{:else}
@@ -97,6 +99,7 @@
 				{regenerateResponse}
 				{mergeResponses}
 				{triggerScroll}
+				{addMessages}
 				{readOnly}
 			/>
 		{/if}

+ 3 - 0
src/lib/components/chat/Messages/MultiResponseMessages.svelte

@@ -36,6 +36,8 @@
 	export let regenerateResponse: Function;
 	export let mergeResponses: Function;
 
+	export let addMessages: Function;
+
 	export let triggerScroll: Function;
 
 	const dispatch = createEventDispatcher();
@@ -233,6 +235,7 @@
 										groupedMessageIdsIdx[modelIdx] =
 											groupedMessageIds[modelIdx].messageIds.length - 1;
 									}}
+									{addMessages}
 									{readOnly}
 								/>
 							{/if}

+ 5 - 0
src/lib/components/chat/Messages/ResponseMessage.svelte

@@ -118,6 +118,8 @@
 	export let continueResponse: Function;
 	export let regenerateResponse: Function;
 
+	export let addMessages: Function;
+
 	export let isLastMessage = true;
 	export let readOnly = false;
 
@@ -634,6 +636,9 @@
 												sourceButton.click();
 											}
 										}}
+										onAddMessages={({ modelId, messages }) => {
+											addMessages({ modelId, messages });
+										}}
 										on:update={(e) => {
 											const { raw, oldContent, newContent } = e.detail;