feat: chat history db code refac for backend support

This commit is contained in:
Timothy J. Baek 2023-11-21 09:39:11 -08:00
parent 14fb5a9b5c
commit c7b1fd1cd1
5 changed files with 111 additions and 178 deletions

View file

@ -20,7 +20,6 @@
export let messages = [];
$: if (messages && messages.length > 0 && (messages.at(-1).done ?? false)) {
console.log('message done: rendering');
(async () => {
await tick();
renderLatex();
@ -32,7 +31,6 @@
const createCopyCodeBlockButton = () => {
// use a class selector if available
let blocks = document.querySelectorAll('pre');
console.log(blocks);
blocks.forEach((block) => {
// only add button if browser supports Clipboard API
@ -195,8 +193,6 @@
};
const rateMessage = async (messageIdx, rating) => {
const chat = await $db.get('chats', chatId);
messages = messages.map((message, idx) => {
if (messageIdx === idx) {
message.rating = rating;
@ -204,14 +200,10 @@
return message;
});
await $db.put('chats', {
...chat,
timestamp: Date.now(),
$db.updateChatById(chatId, {
messages: messages,
history: history
});
console.log(messages);
};
const showPreviousMessage = async (message) => {

View file

@ -21,134 +21,40 @@
let showDropdown = false;
let _chats = $chats.map((item, idx) => $chats[$chats.length - 1 - idx]);
$: if ($chats) {
// Reverse Order
_chats = $chats.map((item, idx) => $chats[$chats.length - 1 - idx]);
}
onMount(async () => {
if (window.innerWidth > 1280) {
show = true;
}
await chats.set(await $db.getAllFromIndex('chats', 'timestamp'));
await chats.set(await $db.getChats());
});
const loadChat = async (id) => {
goto(`/c/${id}`);
// const chat = await db.get('chats', id);
// console.log(chat);
// if (chatId !== chat.id) {
// if ('history' in chat && chat.history !== undefined) {
// history = chat.history;
// } else {
// let _history = {
// messages: {},
// currentId: null
// };
// let parentMessageId = null;
// let messageId = null;
// for (const message of chat.messages) {
// messageId = uuidv4();
// if (parentMessageId !== null) {
// _history.messages[parentMessageId].childrenIds = [
// ..._history.messages[parentMessageId].childrenIds,
// messageId
// ];
// }
// _history.messages[messageId] = {
// ...message,
// id: messageId,
// parentId: parentMessageId,
// childrenIds: []
// };
// parentMessageId = messageId;
// }
// _history.currentId = messageId;
// history = _history;
// }
// if ('models' in chat && chat.models !== undefined) {
// selectedModels = chat.models ?? selectedModels;
// } else {
// selectedModels = [chat.model ?? ''];
// }
// console.log(history);
// title = chat.title;
// chatId = chat.id;
// settings.system = chat.system ?? settings.system;
// settings.temperature = chat.temperature ?? settings.temperature;
// autoScroll = true;
// await tick();
// if (messages.length > 0) {
// history.messages[messages.at(-1).id].done = true;
// }
// }
};
const editChatTitle = async (id, _title) => {
const chat = await $db.get('chats', id);
console.log(chat);
await $db.put('chats', {
...chat,
await $db.updateChatById(id, {
title: _title
});
title = _title;
await chats.set(await $db.getAllFromIndex('chats', 'timestamp'));
};
const deleteChat = async (id) => {
goto('/');
const chat = await $db.delete('chats', id);
console.log(chat);
await chats.set(await $db.getAllFromIndex('chats', 'timestamp'));
$db.deleteChatById(id);
};
const deleteChatHistory = async () => {
const tx = $db.transaction('chats', 'readwrite');
await Promise.all([tx.store.clear(), tx.done]);
await chats.set(await $db.getAllFromIndex('chats', 'timestamp'));
await $db.deleteAllChat();
};
const importChatHistory = async (chatHistory) => {
for (const chat of chatHistory) {
console.log(chat);
await $db.put('chats', {
id: chat.id,
model: chat.model,
models: chat.models,
system: chat.system,
options: chat.options,
title: chat.title,
timestamp: chat.timestamp,
messages: chat.messages,
history: chat.history
});
}
await chats.set(await $db.getAllFromIndex('chats', 'timestamp'));
console.log(chats);
const importChats = async (chatHistory) => {
await $db.addChats(chatHistory);
};
const exportChatHistory = async () => {
await chats.set(await $db.getAllFromIndex('chats', 'timestamp'));
let blob = new Blob([JSON.stringify($chats)], { type: 'application/json' });
const exportChats = async () => {
let blob = new Blob([JSON.stringify(await $db.exportChats())], { type: 'application/json' });
saveAs(blob, `chat-export-${Date.now()}.json`);
};
@ -159,7 +65,7 @@
reader.onload = (event) => {
let chats = JSON.parse(event.target.result);
console.log(chats);
importChatHistory(chats);
importChats(chats);
};
reader.readAsText(importFiles[0]);
@ -238,7 +144,7 @@
</div>
<div class="pl-2.5 my-3 flex-1 flex flex-col space-y-1 overflow-y-auto">
{#each _chats as chat, i}
{#each $chats as chat, i}
<div class=" w-full pr-2 relative">
<button
class=" w-full flex justify-between rounded-md px-3 py-2 hover:bg-gray-900 {chat.id ===
@ -396,7 +302,7 @@
class=" flex rounded-md py-3 px-3.5 w-full hover:bg-gray-900 transition"
on:click={() => {
importFileInputElement.click();
// importChatHistory();
// importChats();
}}
>
<div class=" self-center mr-3">
@ -420,7 +326,7 @@
<button
class=" flex rounded-md py-3 px-3.5 w-full hover:bg-gray-900 transition"
on:click={() => {
exportChatHistory();
exportChats();
}}
>
<div class=" self-center mr-3">

View file

@ -3,7 +3,7 @@
import { onMount, tick } from 'svelte';
import { goto } from '$app/navigation';
import { config, user, showSettings, settings, models, db } from '$lib/stores';
import { config, user, showSettings, settings, models, db, chats } from '$lib/stores';
import SettingsModal from '$lib/components/chat/SettingsModal.svelte';
import Sidebar from '$lib/components/layout/Sidebar.svelte';
@ -77,7 +77,7 @@
};
const getDB = async () => {
return await openDB('Chats', 1, {
const _db = await openDB('Chats', 1, {
upgrade(db) {
const store = db.createObjectStore('chats', {
keyPath: 'id',
@ -86,6 +86,63 @@
store.createIndex('timestamp', 'timestamp');
}
});
return {
db: _db,
getChatById: async function (id) {
return await this.db.get('chats', id);
},
getChats: async function () {
let chats = await this.db.getAllFromIndex('chats', 'timestamp');
chats = chats.map((item, idx) => ({
title: chats[chats.length - 1 - idx].title,
id: chats[chats.length - 1 - idx].id
}));
return chats;
},
exportChats: async function () {
let chats = await this.db.getAllFromIndex('chats', 'timestamp');
chats = chats.map((item, idx) => chats[chats.length - 1 - idx]);
return chats;
},
addChats: async function (_chats) {
for (const chat of _chats) {
console.log(chat);
await this.addChat(chat);
}
await chats.set(await this.db.getChats());
},
addChat: async function (chat) {
await this.db.put('chats', {
...chat
});
},
createNewChat: async function (chat) {
await this.addChat({ ...chat, timestamp: Date.now() });
await chats.set(await this.db.getChats());
},
updateChatById: async function (id, updated) {
const chat = await this.getChatById(id);
await this.db.put('chats', {
...chat,
...updated,
timestamp: Date.now()
});
await chats.set(await this.db.getChats());
},
deleteChatById: async function (id) {
await this.db.delete('chats', id);
await chats.set(await this.db.getChats());
},
deleteAllChat: async function () {
const tx = this.db.transaction('chats', 'readwrite');
await Promise.all([tx.store.clear(), tx.done]);
await chats.set(await this.db.getChats());
}
};
};
onMount(async () => {

View file

@ -71,8 +71,6 @@
//////////////////////////
const sendPrompt = async (userPrompt, parentId) => {
await chats.set(await $db.getAllFromIndex('chats', 'timestamp'));
await Promise.all(
selectedModels.map(async (model) => {
if (model.includes('gpt-')) {
@ -83,9 +81,7 @@
})
);
await chats.set(await $db.getAllFromIndex('chats', 'timestamp'));
console.log(history);
await chats.set(await $db.getChats());
};
const sendPromptOllama = async (model, userPrompt, parentId) => {
@ -189,8 +185,7 @@
window.scrollTo({ top: document.body.scrollHeight });
}
await $db.put('chats', {
id: $chatId,
await $db.updateChatById($chatId, {
title: title === '' ? 'New Chat' : title,
models: selectedModels,
system: $settings.system ?? undefined,
@ -202,8 +197,7 @@
top_p: $settings.top_p ?? undefined
},
messages: messages,
history: history,
timestamp: Date.now()
history: history
});
}
@ -316,11 +310,9 @@
window.scrollTo({ top: document.body.scrollHeight });
}
await $db.put('chats', {
id: $chatId,
await $db.updateChatById($chatId, {
title: title === '' ? 'New Chat' : title,
models: selectedModels,
system: $settings.system ?? undefined,
options: {
seed: $settings.seed ?? undefined,
@ -330,8 +322,7 @@
top_p: $settings.top_p ?? undefined
},
messages: messages,
history: history,
timestamp: Date.now()
history: history
});
}
@ -344,7 +335,6 @@
if (messages.length == 2) {
window.history.replaceState(history.state, '', `/c/${$chatId}`);
await setChatTitle($chatId, userPrompt);
}
}
@ -362,7 +352,6 @@
document.getElementById('chat-textarea').style.height = '';
let userMessageId = uuidv4();
let userMessage = {
id: userMessageId,
parentId: messages.length !== 0 ? messages.at(-1).id : null,
@ -381,7 +370,7 @@
prompt = '';
if (messages.length == 0) {
await $db.put('chats', {
await $db.createNewChat({
id: $chatId,
title: 'New Chat',
models: selectedModels,
@ -394,8 +383,7 @@
top_p: $settings.top_p ?? undefined
},
messages: messages,
history: history,
timestamp: Date.now()
history: history
});
}
@ -459,9 +447,8 @@
};
const setChatTitle = async (_chatId, _title) => {
const chat = await $db.get('chats', _chatId);
await $db.put('chats', { ...chat, title: _title });
if (chat.id === $chatId) {
await $db.updateChatById(_chatId, { title: _title });
if (_chatId === $chatId) {
title = _title;
}
};
@ -469,7 +456,6 @@
<svelte:window
on:scroll={(e) => {
console.log(e);
autoScroll = window.innerHeight + window.scrollY >= document.body.offsetHeight - 40;
}}
/>

View file

@ -42,21 +42,27 @@
messages = _messages;
}
onMount(async () => {
let chat = await loadChat();
// onMount(async () => {
// let chat = await loadChat();
await tick();
if (chat) {
loaded = true;
} else {
await goto('/');
}
});
// await tick();
// if (chat) {
// loaded = true;
// } else {
// await goto('/');
// }
// });
$: if ($page.params.id) {
console.log($page.params.id);
(async () => {
await loadChat();
let chat = await loadChat();
await tick();
if (chat) {
loaded = true;
} else {
await goto('/');
}
})();
}
@ -66,7 +72,7 @@
const loadChat = async () => {
await chatId.set($page.params.id);
const chat = await $db.get('chats', $chatId);
const chat = await $db.getChatById($chatId);
if (chat) {
console.log(chat);
@ -76,10 +82,8 @@
(chat?.history ?? undefined) !== undefined
? chat.history
: convertMessagesToHistory(chat.messages);
console.log(history);
title = chat.title;
await settings.set({
...$settings,
system: chat.system ?? $settings.system,
@ -104,8 +108,6 @@
//////////////////////////
const sendPrompt = async (userPrompt, parentId) => {
await chats.set(await $db.getAllFromIndex('chats', 'timestamp'));
await Promise.all(
selectedModels.map(async (model) => {
if (model.includes('gpt-')) {
@ -116,9 +118,7 @@
})
);
await chats.set(await $db.getAllFromIndex('chats', 'timestamp'));
console.log(history);
await chats.set(await $db.getChats());
};
const sendPromptOllama = async (model, userPrompt, parentId) => {
@ -222,8 +222,7 @@
window.scrollTo({ top: document.body.scrollHeight });
}
await $db.put('chats', {
id: $chatId,
await $db.updateChatById($chatId, {
title: title === '' ? 'New Chat' : title,
models: selectedModels,
system: $settings.system ?? undefined,
@ -235,8 +234,7 @@
top_p: $settings.top_p ?? undefined
},
messages: messages,
history: history,
timestamp: Date.now()
history: history
});
}
@ -247,6 +245,7 @@
}
if (messages.length == 2 && messages.at(1).content !== '') {
window.history.replaceState(history.state, '', `/c/${$chatId}`);
await generateChatTitle($chatId, userPrompt);
}
};
@ -348,11 +347,9 @@
window.scrollTo({ top: document.body.scrollHeight });
}
await $db.put('chats', {
id: $chatId,
await $db.updateChatById($chatId, {
title: title === '' ? 'New Chat' : title,
models: selectedModels,
system: $settings.system ?? undefined,
options: {
seed: $settings.seed ?? undefined,
@ -362,8 +359,7 @@
top_p: $settings.top_p ?? undefined
},
messages: messages,
history: history,
timestamp: Date.now()
history: history
});
}
@ -375,6 +371,7 @@
}
if (messages.length == 2) {
window.history.replaceState(history.state, '', `/c/${$chatId}`);
await setChatTitle($chatId, userPrompt);
}
}
@ -392,7 +389,6 @@
document.getElementById('chat-textarea').style.height = '';
let userMessageId = uuidv4();
let userMessage = {
id: userMessageId,
parentId: messages.length !== 0 ? messages.at(-1).id : null,
@ -411,7 +407,7 @@
prompt = '';
if (messages.length == 0) {
await $db.put('chats', {
await $db.createNewChat({
id: $chatId,
title: 'New Chat',
models: selectedModels,
@ -424,8 +420,7 @@
top_p: $settings.top_p ?? undefined
},
messages: messages,
history: history,
timestamp: Date.now()
history: history
});
}
@ -489,9 +484,8 @@
};
const setChatTitle = async (_chatId, _title) => {
const chat = await $db.get('chats', _chatId);
await $db.put('chats', { ...chat, title: _title });
if (chat.id === $chatId) {
await $db.updateChatById(_chatId, { title: _title });
if (_chatId === $chatId) {
title = _title;
}
};
@ -499,8 +493,6 @@
<svelte:window
on:scroll={(e) => {
console.log(e);
autoScroll = window.innerHeight + window.scrollY >= document.body.offsetHeight - 40;
}}
/>