chat history import/export added

This commit is contained in:
Timothy J. Baek 2023-10-18 22:57:55 -07:00
parent 89399f1a3c
commit d00cc58511
4 changed files with 133 additions and 11 deletions

11
package-lock.json generated
View File

@ -9,6 +9,7 @@
"version": "0.0.1", "version": "0.0.1",
"dependencies": { "dependencies": {
"@sveltejs/adapter-node": "^1.3.1", "@sveltejs/adapter-node": "^1.3.1",
"file-saver": "^2.0.5",
"highlight.js": "^11.9.0", "highlight.js": "^11.9.0",
"idb": "^7.1.1", "idb": "^7.1.1",
"marked": "^9.1.0", "marked": "^9.1.0",
@ -1902,6 +1903,11 @@
"node": "^10.12.0 || >=12.0.0" "node": "^10.12.0 || >=12.0.0"
} }
}, },
"node_modules/file-saver": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
"integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
},
"node_modules/fill-range": { "node_modules/fill-range": {
"version": "7.0.1", "version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@ -5039,6 +5045,11 @@
"flat-cache": "^3.0.4" "flat-cache": "^3.0.4"
} }
}, },
"file-saver": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
"integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
},
"fill-range": { "fill-range": {
"version": "7.0.1", "version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",

View File

@ -33,6 +33,7 @@
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"@sveltejs/adapter-node": "^1.3.1", "@sveltejs/adapter-node": "^1.3.1",
"file-saver": "^2.0.5",
"highlight.js": "^11.9.0", "highlight.js": "^11.9.0",
"idb": "^7.1.1", "idb": "^7.1.1",
"marked": "^9.1.0", "marked": "^9.1.0",

View File

@ -1,13 +1,34 @@
<script lang="ts"> <script lang="ts">
import { onMount } from 'svelte';
let show = false; let show = false;
let navElement; let navElement;
let importFileInputElement;
let importFiles;
export let title: string = 'Ollama Web UI'; export let title: string = 'Ollama Web UI';
export let chats = []; export let chats = [];
export let createNewChat: Function; export let createNewChat: Function;
export let loadChat: Function; export let loadChat: Function;
export let importChatHistory: Function;
export let exportChatHistory: Function;
export let deleteChatHistory: Function; export let deleteChatHistory: Function;
onMount(() => {});
$: if (importFiles) {
console.log(importFiles);
let reader = new FileReader();
reader.onload = (event) => {
let chats = JSON.parse(event.target.result);
console.log(chats);
importChatHistory(chats);
};
reader.readAsText(importFiles[0]);
}
</script> </script>
<div <div
@ -162,8 +183,15 @@
<hr class=" border-gray-800 mb-2 w-full" /> <hr class=" border-gray-800 mb-2 w-full" />
<div class="flex flex-col"> <div class="flex flex-col">
<!-- <div class="flex"> <div class="flex">
<button class=" flex rounded-md p-4 w-full hover:bg-gray-800 transition"> <input bind:this={importFileInputElement} bind:files={importFiles} type="file" hidden />
<button
class=" flex rounded-md p-4 w-full hover:bg-gray-800 transition"
on:click={() => {
importFileInputElement.click();
// importChatHistory();
}}
>
<div class=" self-center mr-3"> <div class=" self-center mr-3">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -182,7 +210,12 @@
</div> </div>
<div class=" self-center">Import</div> <div class=" self-center">Import</div>
</button> </button>
<button class=" flex rounded-md p-4 w-full hover:bg-gray-800 transition"> <button
class=" flex rounded-md p-4 w-full hover:bg-gray-800 transition"
on:click={() => {
exportChatHistory();
}}
>
<div class=" self-center mr-3"> <div class=" self-center mr-3">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -201,7 +234,7 @@
</div> </div>
<div class=" self-center">Export</div> <div class=" self-center">Export</div>
</button> </button>
</div> --> </div>
<button <button
class=" flex rounded-md p-4 w-full hover:bg-gray-800 transition" class=" flex rounded-md p-4 w-full hover:bg-gray-800 transition"
on:click={() => { on:click={() => {

View File

@ -4,6 +4,7 @@
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { marked } from 'marked'; import { marked } from 'marked';
import { saveAs } from 'file-saver';
import hljs from 'highlight.js'; import hljs from 'highlight.js';
import 'highlight.js/styles/dark.min.css'; import 'highlight.js/styles/dark.min.css';
@ -12,7 +13,6 @@
import { openDB, deleteDB } from 'idb'; import { openDB, deleteDB } from 'idb';
import { ENDPOINT as SERVER_ENDPOINT } from '$lib/contants'; import { ENDPOINT as SERVER_ENDPOINT } from '$lib/contants';
import Error from './+error.svelte';
export let data: PageData; export let data: PageData;
$: ({ models, OLLAMA_ENDPOINT } = data); $: ({ models, OLLAMA_ENDPOINT } = data);
@ -22,8 +22,8 @@
let db; let db;
let selectedModel = ''; let selectedModel = '';
let systemPrompt = ''; let system = null;
let temperature = ''; let temperature = null;
let chats = []; let chats = [];
let chatId = uuidv4(); let chatId = uuidv4();
@ -43,8 +43,8 @@
console.log(settings); console.log(settings);
selectedModel = settings.model ?? ''; selectedModel = settings.model ?? '';
systemPrompt = settings.systemPrompt ?? ''; system = settings.system ?? null;
temperature = settings.temperature ?? ''; temperature = settings.temperature ?? null;
} }
db = await openDB('Chats', 1, { db = await openDB('Chats', 1, {
@ -135,9 +135,21 @@
const createNewChat = () => { const createNewChat = () => {
if (messages.length > 0) { if (messages.length > 0) {
chatId = uuidv4();
messages = []; messages = [];
title = ''; title = '';
chatId = uuidv4(); console.log(localStorage.settings.model);
let settings = localStorage.getItem('settings');
if (settings) {
settings = JSON.parse(settings);
console.log(settings);
selectedModel = settings.model ?? selectedModel;
system = settings.system ?? system;
temperature = settings.temperature ?? temperature;
}
} }
}; };
@ -146,6 +158,9 @@
messages = chat.messages; messages = chat.messages;
title = chat.title; title = chat.title;
chatId = chat.id; chatId = chat.id;
selectedModel = chat.model ?? selectedModel;
system = chat.system ?? system;
temperature = chat.temperature ?? temperature;
}; };
const deleteChatHistory = async () => { const deleteChatHistory = async () => {
@ -154,6 +169,31 @@
chats = await db.getAllFromIndex('chats', 'timestamp'); chats = await db.getAllFromIndex('chats', 'timestamp');
}; };
const importChatHistory = async (results) => {
for (const chat of results) {
console.log(chat);
await db.put('chats', {
id: chat.id,
model: chat.model,
system: chat.system,
options: chat.options,
title: chat.title,
timestamp: chat.timestamp,
messages: chat.messages
});
}
chats = await db.getAllFromIndex('chats', 'timestamp');
console.log(chats);
};
const exportChatHistory = async () => {
chats = await db.getAllFromIndex('chats', 'timestamp');
let blob = new Blob([JSON.stringify(chats)], { type: 'application/json' });
saveAs(blob, `chat-export-${Date.now()}.json`);
};
////////////////////////// //////////////////////////
// Ollama functions // Ollama functions
////////////////////////// //////////////////////////
@ -169,6 +209,11 @@
if (messages.length == 0) { if (messages.length == 0) {
await db.put('chats', { await db.put('chats', {
id: chatId, id: chatId,
model: selectedModel,
system: system,
options: {
temperature: temperature
},
title: 'New Chat', title: 'New Chat',
timestamp: Date.now(), timestamp: Date.now(),
messages: messages messages: messages
@ -205,6 +250,13 @@
body: JSON.stringify({ body: JSON.stringify({
model: selectedModel, model: selectedModel,
prompt: user_prompt, prompt: user_prompt,
system: system ?? undefined,
options:
temperature != null
? {
temperature: temperature
}
: undefined,
context: context:
messages.length > 3 && messages.at(-3).context != undefined messages.length > 3 && messages.at(-3).context != undefined
? messages.at(-3).context ? messages.at(-3).context
@ -257,6 +309,11 @@
await db.put('chats', { await db.put('chats', {
id: chatId, id: chatId,
title: title, title: title,
model: selectedModel,
system: system,
options: {
temperature: temperature
},
timestamp: Date.now(), timestamp: Date.now(),
messages: messages messages: messages
}); });
@ -289,6 +346,13 @@
body: JSON.stringify({ body: JSON.stringify({
model: selectedModel, model: selectedModel,
prompt: lastUserMessage.content, prompt: lastUserMessage.content,
system: system ?? undefined,
options:
temperature != null
? {
temperature: temperature
}
: undefined,
context: context:
messages.length > 3 && messages.at(-3).context != undefined messages.length > 3 && messages.at(-3).context != undefined
? messages.at(-3).context ? messages.at(-3).context
@ -337,6 +401,11 @@
await db.put('chats', { await db.put('chats', {
id: chatId, id: chatId,
title: title, title: title,
model: selectedModel,
system: system,
options: {
temperature: temperature
},
timestamp: Date.now(), timestamp: Date.now(),
messages: messages messages: messages
}); });
@ -378,7 +447,15 @@
<div class="app text-gray-100"> <div class="app text-gray-100">
<div class=" bg-gray-800 min-h-screen overflow-auto flex flex-row"> <div class=" bg-gray-800 min-h-screen overflow-auto flex flex-row">
<Navbar {chats} {title} {loadChat} {createNewChat} {deleteChatHistory} /> <Navbar
{chats}
{title}
{loadChat}
{createNewChat}
{importChatHistory}
{exportChatHistory}
{deleteChatHistory}
/>
<div class="min-h-screen w-full flex justify-center"> <div class="min-h-screen w-full flex justify-center">
<div class=" py-2.5 flex flex-col justify-between w-full"> <div class=" py-2.5 flex flex-col justify-between w-full">