From 242be141a95dfb5ec770fd33b1672f0a9244b6a4 Mon Sep 17 00:00:00 2001 From: Webifi Date: Thu, 22 Jun 2023 14:06:51 -0500 Subject: [PATCH 01/17] Multiple prefix prompts --- src/lib/ChatRequest.svelte | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/lib/ChatRequest.svelte b/src/lib/ChatRequest.svelte index 7efc166..e8d6d35 100644 --- a/src/lib/ChatRequest.svelte +++ b/src/lib/ChatRequest.svelte @@ -146,8 +146,8 @@ export class ChatRequest { const maxTokens = getModelMaxTokens(model) const messagePayload = filtered.map((m, i) => { return { role: m.role, content: m.content } }) as Message[] - // Inject hidden prompt if requested - if (!opts.summaryRequest) this.buildHiddenPromptPrefixMessage(messagePayload, true) + // Inject hidden prompts if requested + if (!opts.summaryRequest) this.buildHiddenPromptPrefixMessages(messagePayload, true) const chatResponse = new ChatCompletionResponse(opts) const promptTokenCount = countPromptTokens(messagePayload, model) @@ -288,26 +288,35 @@ export class ChatRequest { return this.chat.settings.model || defaultModel } - private buildHiddenPromptPrefixMessage (messages: Message[], insert:boolean = false): Message|null { + private buildHiddenPromptPrefixMessages (messages: Message[], insert:boolean = false): Message[] { const chatSettings = this.chat.settings const hiddenPromptPrefix = mergeProfileFields(chatSettings, chatSettings.hiddenPromptPrefix).trim() if (hiddenPromptPrefix && messages.length && messages[messages.length - 1].role === 'user') { - const message = { role: 'user', content: hiddenPromptPrefix } as Message + const results = hiddenPromptPrefix.split(/[\s\r\n]*::EOM::[\s\r\n]*/).reduce((a, m) => { + m = m.trim() + if (m.length) { + a.push({ role: a.length % 2 === 0 ? 'user' : 'assistant', content: m } as Message) + } + return a + }, [] as Message[]) if (insert) { - messages.splice(messages.length - 1, 0, message) + results.forEach(m => { messages.splice(messages.length - 1, 0, m) }) } - return message + return results } - return null + return [] } + /** + * Gets an estimate of how many extra tokens will be added that won't be part of the visible messages + * @param filtered + */ private getTokenCountPadding (filtered: Message[]): number { - const hiddenPromptMessage = this.buildHiddenPromptPrefixMessage(filtered) let result = 0 - if (hiddenPromptMessage) { - // add cost of hiddenPromptPrefix - result += countMessageTokens(hiddenPromptMessage, this.getModel()) - } + // add cost of hiddenPromptPrefix + result += this.buildHiddenPromptPrefixMessages(filtered) + .reduce((a, m) => a + countMessageTokens(m, this.getModel()), 0) + // more here eventually? return result } From 4858f4361aec372dd8b803865638e07b03c1a04b Mon Sep 17 00:00:00 2001 From: Webifi Date: Thu, 22 Jun 2023 14:07:00 -0500 Subject: [PATCH 02/17] Profile tweaks --- src/lib/Profiles.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/Profiles.svelte b/src/lib/Profiles.svelte index a9e4bba..7e59db1 100644 --- a/src/lib/Profiles.svelte +++ b/src/lib/Profiles.svelte @@ -244,7 +244,7 @@ Um, how's your drink? ...chatDefaults, characterName: 'Ivan', profileName: 'Ivan - A very personal assistant', - profileDescription: 'Iris is a friend that\'s here to help.', + profileDescription: 'Ivan is a friend that\'s here to help.', useSystemPrompt: true, temperature: 1.15, presence_penalty: 0.3, From 3314252c3cd4f11e462a26b746619f7a2e98bc00 Mon Sep 17 00:00:00 2001 From: Webifi Date: Thu, 22 Jun 2023 20:58:57 -0500 Subject: [PATCH 03/17] Add hint for multiple hidden prefix prompts --- src/lib/Settings.svelte | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/Settings.svelte b/src/lib/Settings.svelte index 5243629..3ff88c7 100644 --- a/src/lib/Settings.svelte +++ b/src/lib/Settings.svelte @@ -179,9 +179,9 @@ const systemPromptSettings: ChatSetting[] = [ }, { key: 'hiddenPromptPrefix', - name: 'Hidden Prompt Prefix', - title: 'A user prompt that will be silently injected before every new user prompt, then removed from history.', - placeholder: 'Enter user prompt prefix here. You can remind ChatGPT how to act.', + name: 'Hidden Prompts Prefix', + title: 'Prompts that will be silently injected before every new user prompt, then removed from history.', + placeholder: 'Enter user prompt prefix here. You can remind ChatGPT how to act. Use ::EOM:: to separate messages.', type: 'textarea', hide: (chatId) => !getChatSettings(chatId).useSystemPrompt }, From 2098bc7a0b16d4dd4744bf9962db2b1501e41a32 Mon Sep 17 00:00:00 2001 From: Webifi Date: Thu, 22 Jun 2023 21:08:50 -0500 Subject: [PATCH 04/17] Add new chat from current to chat option menu --- src/lib/ChatOptionMenu.svelte | 7 +++++-- src/lib/Util.svelte | 8 +++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/lib/ChatOptionMenu.svelte b/src/lib/ChatOptionMenu.svelte index 514d76f..42d6724 100644 --- a/src/lib/ChatOptionMenu.svelte +++ b/src/lib/ChatOptionMenu.svelte @@ -24,7 +24,7 @@ import { clickOutside } from 'svelte-use-click-outside' import { openModal } from 'svelte-modals' import PromptConfirm from './PromptConfirm.svelte' - import { startNewChatWithWarning } from './Util.svelte' + import { startNewChatWithWarning, startNewChatFromChatId } from './Util.svelte' export let chatId export const show = (showHide:boolean = true) => { @@ -123,7 +123,10 @@ { $apiKeyStorage && close(); $apiKeyStorage && startNewChatWithWarning(chatId) }} class="dropdown-item"> - New Chat + New Chat from Default + + { chatId && close(); chatId && startNewChatFromChatId(chatId) }} class="dropdown-item"> + New Chat from Current { if (chatId) close(); copyChat(chatId) }}> Clone Chat diff --git a/src/lib/Util.svelte b/src/lib/Util.svelte index 39831b8..5c4b9c9 100644 --- a/src/lib/Util.svelte +++ b/src/lib/Util.svelte @@ -2,7 +2,7 @@ import { compare } from 'stacking-order' import { openModal } from 'svelte-modals' import PromptNotice from './PromptNotice.svelte' - import { getChat } from './Storage.svelte' + import { addChat, getChat } from './Storage.svelte' import { replace } from 'svelte-spa-router' import PromptConfirm from './PromptConfirm.svelte' export const sizeTextElements = () => { @@ -115,6 +115,12 @@ }) } + export const startNewChatFromChatId = (chatId: number) => { + const newChatId = addChat(getChat(chatId).settings) + // go to new chat + replace(`/chat/${newChatId}`) + } + export const startNewChatWithWarning = (activeChatId: number|undefined) => { if (activeChatId && getChat(activeChatId).settings.isDirty) { openModal(PromptConfirm, { From 69f514a69fbca92541c16225544fb78505dde287 Mon Sep 17 00:00:00 2001 From: Webifi Date: Thu, 22 Jun 2023 21:15:25 -0500 Subject: [PATCH 05/17] change chat from current icon --- src/lib/ChatOptionMenu.svelte | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/ChatOptionMenu.svelte b/src/lib/ChatOptionMenu.svelte index 42d6724..c9d17fc 100644 --- a/src/lib/ChatOptionMenu.svelte +++ b/src/lib/ChatOptionMenu.svelte @@ -17,6 +17,7 @@ faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons/index' + import { faSquarePlus as faSquarePlusOutline } from '@fortawesome/free-regular-svg-icons/index' import { apiKeyStorage, addChatFromJSON, chatsStorage, checkStateChange, clearChats, clearMessages, copyChat, globalStorage, setGlobalSettingValueByKey, showSetChatSettings, pinMainMenu, getChat, deleteChat } from './Storage.svelte' import { exportAsMarkdown, exportChatAsJSON } from './Export.svelte' import { restartProfile } from './Profiles.svelte' @@ -126,7 +127,7 @@ New Chat from Default { chatId && close(); chatId && startNewChatFromChatId(chatId) }} class="dropdown-item"> - New Chat from Current + New Chat from Current { if (chatId) close(); copyChat(chatId) }}> Clone Chat From 86092afcb0d4ed6387bae1ceaa1a1aa85e20f1a3 Mon Sep 17 00:00:00 2001 From: Webifi Date: Sat, 24 Jun 2023 09:18:29 -0500 Subject: [PATCH 06/17] Add lastChatId, but disable use for now --- src/lib/Home.svelte | 17 ++++++++++++++++- src/lib/Storage.svelte | 4 ++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/lib/Home.svelte b/src/lib/Home.svelte index e879077..8c49809 100644 --- a/src/lib/Home.svelte +++ b/src/lib/Home.svelte @@ -1,9 +1,24 @@
diff --git a/src/lib/Storage.svelte b/src/lib/Storage.svelte index bebd2aa..034dd9c 100644 --- a/src/lib/Storage.svelte +++ b/src/lib/Storage.svelte @@ -20,7 +20,9 @@ export let pinMainMenu = writable(false) // Show menu (for mobile use) export let continueMessage = writable('') // export let currentChatMessages = writable([] as Message[]) + export let started = writable(false) export let currentChatId = writable(0) + export let lastChatId = persisted('currentChatId', 0) const chatDefaults = getChatDefaults() @@ -227,10 +229,12 @@ clearTimeout(setChatTimer) if (!chatId) { currentChatId.set(0) + lastChatId.set(0) currentChatMessages.set([]) } setChatTimer = setTimeout(() => { currentChatId.set(chatId) + lastChatId.set(chatId) currentChatMessages.set(getChat(chatId).messages) }, 10) } From 8835ee1d6e890b925327c3f2c64fd735b1db3aa4 Mon Sep 17 00:00:00 2001 From: Webifi Date: Sat, 24 Jun 2023 12:48:27 -0500 Subject: [PATCH 07/17] chat and message date data, begin chat sort opts. --- src/lib/Chat.svelte | 4 ++++ src/lib/Settings.svelte | 9 +++++++++ src/lib/Sidebar.svelte | 2 +- src/lib/Storage.svelte | 16 +++++++++++++--- src/lib/Types.svelte | 9 ++++++++- 5 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/lib/Chat.svelte b/src/lib/Chat.svelte index 418c53e..1262bf7 100644 --- a/src/lib/Chat.svelte +++ b/src/lib/Chat.svelte @@ -115,6 +115,10 @@ chatRequest = new ChatRequest() chatRequest.setChat(chat) + + chat.lastAccess = Date.now() + saveChatStore() + // Focus the input on mount focusInput() diff --git a/src/lib/Settings.svelte b/src/lib/Settings.svelte index 3ff88c7..c20897b 100644 --- a/src/lib/Settings.svelte +++ b/src/lib/Settings.svelte @@ -105,6 +105,15 @@ export const imageGenerationSizes = [ export const imageGenerationSizeTypes = ['', ...imageGenerationSizes] +export const chatSortOptions = [ + { value: 'name', text: 'Name' }, + { value: 'created', text: 'Created' }, + { value: 'updated', text: 'Last Use' }, + { value: 'lastAccess', text: 'Last View' } +] + +export const chatSortOptionsKeys = chatSortOptions.map(o => o.value, [] as string[]) + const profileSetting: ChatSetting & SettingSelect = { key: 'profile', name: 'Profile', diff --git a/src/lib/Sidebar.svelte b/src/lib/Sidebar.svelte index 3f8d1d4..7c8132c 100644 --- a/src/lib/Sidebar.svelte +++ b/src/lib/Sidebar.svelte @@ -9,7 +9,7 @@ import { clickOutside } from 'svelte-use-click-outside' import { startNewChatWithWarning } from './Util.svelte' - $: sortedChats = $chatsStorage.sort((a, b) => b.id - a.id) + $: sortedChats = $chatsStorage.sort((a, b) => ((b.created || 0) - (a.created || 0)) || (b.id - a.id)) $: activeChatId = $params && $params.chatId ? parseInt($params.chatId) : undefined diff --git a/src/lib/Storage.svelte b/src/lib/Storage.svelte index 034dd9c..fea3858 100644 --- a/src/lib/Storage.svelte +++ b/src/lib/Storage.svelte @@ -52,7 +52,10 @@ messages: [], usage: {} as Record, startSession: false, - sessionStarted: false + sessionStarted: false, + created: Date.now(), + updated: Date.now(), + lastAccess: Date.now() }) chatsStorage.set(chats) // Apply defaults and prepare it to start @@ -79,6 +82,7 @@ } chat.id = chatId + chat.created = Date.now() // Make sure images are moved to indexedDB store, // else they would clobber local storage @@ -252,7 +256,9 @@ }, 200) } else { clearTimeout(setMessagesTimers[chatId]) - getChat(chatId).messages = messages + const chat = getChat(chatId) + chat.updated = Date.now() + chat.messages = messages saveChatStore() } } @@ -268,6 +274,7 @@ export const addMessage = (chatId: number, message: Message) => { const messages = getMessages(chatId) if (!message.uuid) message.uuid = uuidv4() + if (!message.created) message.created = Date.now() if (messages.indexOf(message) < 0) { // Don't have message, add it messages[messages.length] = message @@ -286,7 +293,10 @@ console.error("Couldn't insert after message:", insertAfter) return } - newMessages.forEach(m => { m.uuid = m.uuid || uuidv4() }) + newMessages.forEach(m => { + m.uuid = m.uuid || uuidv4() + m.created = m.created || Date.now() + }) messages.splice(index + 1, 0, ...newMessages) setMessages(chatId, messages.filter(m => true)) } diff --git a/src/lib/Types.svelte b/src/lib/Types.svelte index be81424..9bc4422 100644 --- a/src/lib/Types.svelte +++ b/src/lib/Types.svelte @@ -1,11 +1,13 @@ diff --git a/src/lib/Storage.svelte b/src/lib/Storage.svelte index fea3858..9803f7a 100644 --- a/src/lib/Storage.svelte +++ b/src/lib/Storage.svelte @@ -1,8 +1,8 @@