From 195cfd4f843e528b219011633c8ba477e4587b4d Mon Sep 17 00:00:00 2001 From: Rohit Das <43847374+therohitdas@users.noreply.github.com> Date: Mon, 11 Dec 2023 15:58:49 +0530 Subject: [PATCH 01/10] wip: displaying error in a toast --- src/routes/(app)/+page.svelte | 130 ++++++++++++++------------- src/routes/(app)/c/[id]/+page.svelte | 130 ++++++++++++++------------- 2 files changed, 140 insertions(+), 120 deletions(-) diff --git a/src/routes/(app)/+page.svelte b/src/routes/(app)/+page.svelte index c0d210fc6..e7d522b1c 100644 --- a/src/routes/(app)/+page.svelte +++ b/src/routes/(app)/+page.svelte @@ -191,80 +191,90 @@ }) }); - const reader = res.body - .pipeThrough(new TextDecoderStream()) - .pipeThrough(splitStream('\n')) - .getReader(); - - while (true) { - const { value, done } = await reader.read(); - if (done || stopResponseFlag || _chatId !== $chatId) { - responseMessage.done = true; - messages = messages; - break; + if (!res.ok) { + const error = await res.json(); + console.log(error); + if ('detail' in error) { + toast.error(error.detail); + } else { + toast.error(error.error); } + } else { + const reader = res.body + .pipeThrough(new TextDecoderStream()) + .pipeThrough(splitStream('\n')) + .getReader(); - try { - let lines = value.split('\n'); + while (true) { + const { value, done } = await reader.read(); + if (done || stopResponseFlag || _chatId !== $chatId) { + responseMessage.done = true; + messages = messages; + break; + } - for (const line of lines) { - if (line !== '') { - console.log(line); - let data = JSON.parse(line); + try { + let lines = value.split('\n'); - if ('detail' in data) { - throw data; - } + for (const line of lines) { + if (line !== '') { + console.log(line); + let data = JSON.parse(line); - if (data.done == false) { - if (responseMessage.content == '' && data.message.content == '\n') { - continue; + if ('detail' in data) { + throw data; + } + + if (data.done == false) { + if (responseMessage.content == '' && data.message.content == '\n') { + continue; + } else { + responseMessage.content += data.message.content; + messages = messages; + } } else { - responseMessage.content += data.message.content; + responseMessage.done = true; + responseMessage.context = data.context ?? null; + responseMessage.info = { + total_duration: data.total_duration, + prompt_eval_count: data.prompt_eval_count, + prompt_eval_duration: data.prompt_eval_duration, + eval_count: data.eval_count, + eval_duration: data.eval_duration + }; messages = messages; } - } else { - responseMessage.done = true; - responseMessage.context = data.context ?? null; - responseMessage.info = { - total_duration: data.total_duration, - prompt_eval_count: data.prompt_eval_count, - prompt_eval_duration: data.prompt_eval_duration, - eval_count: data.eval_count, - eval_duration: data.eval_duration - }; - messages = messages; } } + } catch (error) { + console.log(error); + if ('detail' in error) { + toast.error(error.detail); + } + break; } - } catch (error) { - console.log(error); - if ('detail' in error) { - toast.error(error.detail); + + if (autoScroll) { + window.scrollTo({ top: document.body.scrollHeight }); } - break; - } - if (autoScroll) { - window.scrollTo({ top: document.body.scrollHeight }); + await $db.updateChatById(_chatId, { + title: title === '' ? 'New Chat' : title, + models: selectedModels, + system: $settings.system ?? undefined, + options: { + seed: $settings.seed ?? undefined, + temperature: $settings.temperature ?? undefined, + repeat_penalty: $settings.repeat_penalty ?? undefined, + top_k: $settings.top_k ?? undefined, + top_p: $settings.top_p ?? undefined, + num_ctx: $settings.num_ctx ?? undefined, + ...($settings.options ?? {}) + }, + messages: messages, + history: history + }); } - - await $db.updateChatById(_chatId, { - title: title === '' ? 'New Chat' : title, - models: selectedModels, - system: $settings.system ?? undefined, - options: { - seed: $settings.seed ?? undefined, - temperature: $settings.temperature ?? undefined, - repeat_penalty: $settings.repeat_penalty ?? undefined, - top_k: $settings.top_k ?? undefined, - top_p: $settings.top_p ?? undefined, - num_ctx: $settings.num_ctx ?? undefined, - ...($settings.options ?? {}) - }, - messages: messages, - history: history - }); } stopResponseFlag = false; diff --git a/src/routes/(app)/c/[id]/+page.svelte b/src/routes/(app)/c/[id]/+page.svelte index fd61a4dc8..ff2a9b17a 100644 --- a/src/routes/(app)/c/[id]/+page.svelte +++ b/src/routes/(app)/c/[id]/+page.svelte @@ -218,80 +218,90 @@ }) }); - const reader = res.body - .pipeThrough(new TextDecoderStream()) - .pipeThrough(splitStream('\n')) - .getReader(); - - while (true) { - const { value, done } = await reader.read(); - if (done || stopResponseFlag || _chatId !== $chatId) { - responseMessage.done = true; - messages = messages; - break; + if (!res.ok) { + const error = await res.json(); + console.log(error); + if ('detail' in error) { + toast.error(error.detail); + } else { + toast.error(error.error); } + } else { + const reader = res.body + .pipeThrough(new TextDecoderStream()) + .pipeThrough(splitStream('\n')) + .getReader(); - try { - let lines = value.split('\n'); + while (true) { + const { value, done } = await reader.read(); + if (done || stopResponseFlag || _chatId !== $chatId) { + responseMessage.done = true; + messages = messages; + break; + } - for (const line of lines) { - if (line !== '') { - console.log(line); - let data = JSON.parse(line); + try { + let lines = value.split('\n'); - if ('detail' in data) { - throw data; - } + for (const line of lines) { + if (line !== '') { + console.log(line); + let data = JSON.parse(line); - if (data.done == false) { - if (responseMessage.content == '' && data.message.content == '\n') { - continue; + if ('detail' in data) { + throw data; + } + + if (data.done == false) { + if (responseMessage.content == '' && data.message.content == '\n') { + continue; + } else { + responseMessage.content += data.message.content; + messages = messages; + } } else { - responseMessage.content += data.message.content; + responseMessage.done = true; + responseMessage.context = data.context ?? null; + responseMessage.info = { + total_duration: data.total_duration, + prompt_eval_count: data.prompt_eval_count, + prompt_eval_duration: data.prompt_eval_duration, + eval_count: data.eval_count, + eval_duration: data.eval_duration + }; messages = messages; } - } else { - responseMessage.done = true; - responseMessage.context = data.context ?? null; - responseMessage.info = { - total_duration: data.total_duration, - prompt_eval_count: data.prompt_eval_count, - prompt_eval_duration: data.prompt_eval_duration, - eval_count: data.eval_count, - eval_duration: data.eval_duration - }; - messages = messages; } } + } catch (error) { + console.log(error); + if ('detail' in error) { + toast.error(error.detail); + } + break; } - } catch (error) { - console.log(error); - if ('detail' in error) { - toast.error(error.detail); + + if (autoScroll) { + window.scrollTo({ top: document.body.scrollHeight }); } - break; - } - if (autoScroll) { - window.scrollTo({ top: document.body.scrollHeight }); + await $db.updateChatById(_chatId, { + title: title === '' ? 'New Chat' : title, + models: selectedModels, + system: $settings.system ?? undefined, + options: { + seed: $settings.seed ?? undefined, + temperature: $settings.temperature ?? undefined, + repeat_penalty: $settings.repeat_penalty ?? undefined, + top_k: $settings.top_k ?? undefined, + top_p: $settings.top_p ?? undefined, + num_ctx: $settings.num_ctx ?? undefined, + ...($settings.options ?? {}) + }, + messages: messages, + history: history + }); } - - await $db.updateChatById(_chatId, { - title: title === '' ? 'New Chat' : title, - models: selectedModels, - system: $settings.system ?? undefined, - options: { - seed: $settings.seed ?? undefined, - temperature: $settings.temperature ?? undefined, - repeat_penalty: $settings.repeat_penalty ?? undefined, - top_k: $settings.top_k ?? undefined, - top_p: $settings.top_p ?? undefined, - num_ctx: $settings.num_ctx ?? undefined, - ...($settings.options ?? {}) - }, - messages: messages, - history: history - }); } stopResponseFlag = false; From e55a5dafdeb2bd0c88fb028def175817eecc2d90 Mon Sep 17 00:00:00 2001 From: Samuel Skottenborg Date: Mon, 11 Dec 2023 17:06:55 +0100 Subject: [PATCH 02/10] Added model dropdown for deleting local models --- src/lib/components/chat/SettingsModal.svelte | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/lib/components/chat/SettingsModal.svelte b/src/lib/components/chat/SettingsModal.svelte index a0d538aa4..406b1b233 100644 --- a/src/lib/components/chat/SettingsModal.svelte +++ b/src/lib/components/chat/SettingsModal.svelte @@ -751,11 +751,20 @@
Delete a model
- + placeholder="Select a model" + > + {#if !deleteModelTag} + + {/if} + {#each $models.filter((m) => m.size != null) as model} + + {/each} +
{:else}
- {@html marked(message.content.replace('\\\\', '\\\\\\'))} + {#if message?.error === true} +
+ + + + +
+ {message.content} +
+
+ {:else} + {@html marked(message.content.replace('\\\\', '\\\\\\'))} + {/if} {#if message.done}
diff --git a/src/routes/(app)/+page.svelte b/src/routes/(app)/+page.svelte index f6bf0e350..44c923978 100644 --- a/src/routes/(app)/+page.svelte +++ b/src/routes/(app)/+page.svelte @@ -276,12 +276,20 @@ console.log(error); if ('detail' in error) { toast.error(error.detail); + responseMessage.content = error.detail; } else { toast.error(error.error); + responseMessage.content = error.error; } } else { toast.error(`Uh-oh! There was an issue connecting to Ollama.`); + responseMessage.content = `Uh-oh! There was an issue connecting to Ollama.`; } + + responseMessage.error = true; + responseMessage.content = `Uh-oh! There was an issue connecting to Ollama.`; + responseMessage.done = true; + messages = messages; } stopResponseFlag = false; diff --git a/src/routes/(app)/c/[id]/+page.svelte b/src/routes/(app)/c/[id]/+page.svelte index 3eec7a5e9..c2685af59 100644 --- a/src/routes/(app)/c/[id]/+page.svelte +++ b/src/routes/(app)/c/[id]/+page.svelte @@ -303,12 +303,20 @@ console.log(error); if ('detail' in error) { toast.error(error.detail); + responseMessage.content = error.detail; } else { toast.error(error.error); + responseMessage.content = error.error; } } else { toast.error(`Uh-oh! There was an issue connecting to Ollama.`); + responseMessage.content = `Uh-oh! There was an issue connecting to Ollama.`; } + + responseMessage.error = true; + responseMessage.content = `Uh-oh! There was an issue connecting to Ollama.`; + responseMessage.done = true; + messages = messages; } stopResponseFlag = false; From 0b1abf164345f774e17c2cbe2c5190c70b4ce597 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Wed, 13 Dec 2023 15:35:35 -0800 Subject: [PATCH 06/10] chore: commented code removed --- src/routes/(app)/+page.svelte | 31 ---------------------------- src/routes/(app)/c/[id]/+page.svelte | 31 ---------------------------- 2 files changed, 62 deletions(-) diff --git a/src/routes/(app)/+page.svelte b/src/routes/(app)/+page.svelte index c0d210fc6..3fbb700af 100644 --- a/src/routes/(app)/+page.svelte +++ b/src/routes/(app)/+page.svelte @@ -106,7 +106,6 @@ const sendPromptOllama = async (model, userPrompt, parentId, _chatId) => { console.log('sendPromptOllama'); let responseMessageId = uuidv4(); - let responseMessage = { parentId: parentId, id: responseMessageId, @@ -126,38 +125,8 @@ } await tick(); - window.scrollTo({ top: document.body.scrollHeight }); - // const res = await fetch(`${$settings?.API_BASE_URL ?? OLLAMA_API_BASE_URL}/generate`, { - // method: 'POST', - // headers: { - // 'Content-Type': 'text/event-stream', - // ...($settings.authHeader && { Authorization: $settings.authHeader }), - // ...($user && { Authorization: `Bearer ${localStorage.token}` }) - // }, - // body: JSON.stringify({ - // model: model, - // prompt: userPrompt, - // system: $settings.system ?? undefined, - // options: { - // seed: $settings.seed ?? undefined, - // temperature: $settings.temperature ?? undefined, - // repeat_penalty: $settings.repeat_penalty ?? undefined, - // top_k: $settings.top_k ?? undefined, - // top_p: $settings.top_p ?? undefined, - // num_ctx: $settings.num_ctx ?? undefined, - // ...($settings.options ?? {}) - // }, - // format: $settings.requestFormat ?? undefined, - // context: - // history.messages[parentId] !== null && - // history.messages[parentId].parentId in history.messages - // ? history.messages[history.messages[parentId].parentId]?.context ?? undefined - // : undefined - // }) - // }); - const res = await fetch(`${$settings?.API_BASE_URL ?? OLLAMA_API_BASE_URL}/chat`, { method: 'POST', headers: { diff --git a/src/routes/(app)/c/[id]/+page.svelte b/src/routes/(app)/c/[id]/+page.svelte index fd61a4dc8..189909979 100644 --- a/src/routes/(app)/c/[id]/+page.svelte +++ b/src/routes/(app)/c/[id]/+page.svelte @@ -133,7 +133,6 @@ const sendPromptOllama = async (model, userPrompt, parentId, _chatId) => { console.log('sendPromptOllama'); let responseMessageId = uuidv4(); - let responseMessage = { parentId: parentId, id: responseMessageId, @@ -153,38 +152,8 @@ } await tick(); - window.scrollTo({ top: document.body.scrollHeight }); - // const res = await fetch(`${$settings?.API_BASE_URL ?? OLLAMA_API_BASE_URL}/generate`, { - // method: 'POST', - // headers: { - // 'Content-Type': 'text/event-stream', - // ...($settings.authHeader && { Authorization: $settings.authHeader }), - // ...($user && { Authorization: `Bearer ${localStorage.token}` }) - // }, - // body: JSON.stringify({ - // model: model, - // prompt: userPrompt, - // system: $settings.system ?? undefined, - // options: { - // seed: $settings.seed ?? undefined, - // temperature: $settings.temperature ?? undefined, - // repeat_penalty: $settings.repeat_penalty ?? undefined, - // top_k: $settings.top_k ?? undefined, - // top_p: $settings.top_p ?? undefined, - // num_ctx: $settings.num_ctx ?? undefined, - // ...($settings.options ?? {}) - // }, - // format: $settings.requestFormat ?? undefined, - // context: - // history.messages[parentId] !== null && - // history.messages[parentId].parentId in history.messages - // ? history.messages[history.messages[parentId].parentId]?.context ?? undefined - // : undefined - // }) - // }); - const res = await fetch(`${$settings?.API_BASE_URL ?? OLLAMA_API_BASE_URL}/chat`, { method: 'POST', headers: { From 9b12cdcf83f36b65c33989915667c9c4298d3bc8 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Wed, 13 Dec 2023 16:21:50 -0800 Subject: [PATCH 07/10] feat: image upload support --- src/lib/components/chat/MessageInput.svelte | 63 +++++++++++---------- src/lib/components/chat/Messages.svelte | 38 +++++++++---- src/routes/(app)/+page.svelte | 17 +++++- src/routes/(app)/c/[id]/+page.svelte | 23 ++++---- 4 files changed, 84 insertions(+), 57 deletions(-) diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index 015e6e3a4..bc3a6a9d2 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -14,7 +14,7 @@ export let files = []; - export let fileUploadEnabled = false; + export let fileUploadEnabled = true; export let speechRecognitionEnabled = true; export let speechRecognitionListening = false; @@ -84,40 +84,40 @@ }; -
-
-
- {#if messages.length == 0 && suggestionPrompts.length !== 0} +
+
+ {#if messages.length == 0 && suggestionPrompts.length !== 0} +
- {/if} +
+ {/if} - {#if autoScroll === false && messages.length > 0} -
- -
- {/if} -
+ + + +
+ {/if}
-
+
{ + await tick(); + window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' }); + })(); + } + const speakMessage = (message) => { const speak = new SpeechSynthesisUtterance(message); speechSynthesis.speak(speak); @@ -184,7 +192,8 @@ parentId: history.messages[messageId].parentId, childrenIds: [], role: 'user', - content: userPrompt + content: userPrompt, + ...(history.messages[messageId].files && { files: history.messages[messageId].files }) }; let messageParentId = history.messages[messageId].parentId; @@ -425,6 +434,18 @@ class="prose chat-{message.role} w-full max-w-full dark:prose-invert prose-headings:my-0 prose-p:my-0 prose-p:-mb-4 prose-pre:my-0 prose-table:my-0 prose-blockquote:my-0 prose-img:my-0 prose-ul:-my-4 prose-ol:-my-4 prose-li:-my-3 prose-ul:-mb-6 prose-ol:-mb-6 prose-li:-mb-4 whitespace-pre-line" > {#if message.role == 'user'} + {#if message.files} +
+ {#each message.files as file} +
+ {#if file.type === 'image'} + input + {/if} +
+ {/each} +
+ {/if} + {#if message?.edit === true}