ソースを参照

chat event stream behaviour updated

Timothy J. Baek 1 年間 前
コミット
83ae37f154
1 ファイル変更51 行追加18 行削除
  1. 51 18
      src/routes/+page.svelte

+ 51 - 18
src/routes/+page.svelte

@@ -18,19 +18,41 @@
 
 	let textareaElement = '';
 
+	const splitStream = (splitOn) => {
+		let buffer = '';
+		return new TransformStream({
+			transform(chunk, controller) {
+				buffer += chunk;
+				const parts = buffer.split(splitOn);
+				parts.slice(0, -1).forEach((part) => controller.enqueue(part));
+				buffer = parts[parts.length - 1];
+			},
+			flush(controller) {
+				if (buffer) controller.enqueue(buffer);
+			}
+		});
+	};
+
 	const submitPrompt = async () => {
 		console.log('submitPrompt');
+
 		if (selectedModel !== '') {
 			console.log(prompt);
 
 			let user_prompt = prompt;
+
 			chatHistory[Object.keys(chatHistory).length] = {
 				role: 'user',
 				content: user_prompt
 			};
+
 			prompt = '';
 			textareaElement.style.height = '';
 
+			setTimeout(() => {
+				window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' });
+			}, 50);
+
 			const res = await fetch(`${ENDPOINT}/api/generate`, {
 				method: 'POST',
 				headers: {
@@ -47,36 +69,47 @@
 				role: 'assistant',
 				content: ''
 			};
+			window.scrollTo({ top: document.body.scrollHeight });
 
-			const reader = res.body.pipeThrough(new TextDecoderStream()).getReader();
+			const reader = res.body
+				.pipeThrough(new TextDecoderStream())
+				.pipeThrough(splitStream('\n'))
+				.getReader();
 			while (true) {
 				const { value, done } = await reader.read();
 				if (done) break;
 
-				// toast.success(value);
 				try {
-					let data = JSON.parse(value);
-					console.log(data);
-
-					if (data.done == false) {
-						if (
-							chatHistory[Object.keys(chatHistory).length - 1].content == '' &&
-							data.response == '\n'
-						) {
-							continue;
-						} else {
-							chatHistory[Object.keys(chatHistory).length - 1].content += data.response;
+					let lines = value.split('\n');
+
+					for (const line of lines) {
+						if (line !== '') {
+							console.log(line);
+							let data = JSON.parse(line);
+
+							if (data.done == false) {
+								if (
+									chatHistory[Object.keys(chatHistory).length - 1].content == '' &&
+									data.response == '\n'
+								) {
+									continue;
+								} else {
+									chatHistory[Object.keys(chatHistory).length - 1].content += data.response;
+								}
+							} else {
+								context = data.context;
+								console.log(context);
+								chatHistory[Object.keys(chatHistory).length - 1].done = true;
+							}
 						}
-					} else {
-						context = data.context;
-						console.log(context);
-						chatHistory[Object.keys(chatHistory).length - 1].done = true;
 					}
 				} catch (error) {
 					console.log(error);
 				}
-				window.scrollTo(0, document.body.scrollHeight);
+				window.scrollTo({ top: document.body.scrollHeight });
 			}
+
+			window.scrollTo({ top: document.body.scrollHeight });
 		} else {
 			toast.error('Model not selected');
 		}