Browse Source

feat: memory integration

Timothy J. Baek 1 year ago
parent
commit
a8c4588fb5

+ 1 - 1
backend/apps/web/routers/memories.py

@@ -72,7 +72,7 @@ class QueryMemoryForm(BaseModel):
 
 
 @router.post("/query", response_model=Optional[MemoryModel])
-async def add_memory(
+async def query_memory(
     request: Request, form_data: QueryMemoryForm, user=Depends(get_verified_user)
 ):
     query_embedding = request.app.state.EMBEDDING_FUNCTION(form_data.content)

+ 123 - 0
src/lib/apis/memories/index.ts

@@ -0,0 +1,123 @@
+import { WEBUI_API_BASE_URL } from '$lib/constants';
+
+export const getMemories = async (token: string) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/memories`, {
+		method: 'GET',
+		headers: {
+			Accept: 'application/json',
+			'Content-Type': 'application/json',
+			authorization: `Bearer ${token}`
+		}
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.catch((err) => {
+			error = err.detail;
+			console.log(err);
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
+export const addNewMemory = async (token: string, content: string) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/memories/add`, {
+		method: 'POST',
+		headers: {
+			Accept: 'application/json',
+			'Content-Type': 'application/json',
+			authorization: `Bearer ${token}`
+		},
+		body: JSON.stringify({
+			content: content
+		})
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.catch((err) => {
+			error = err.detail;
+			console.log(err);
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
+export const queryMemory = async (token: string, content: string) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/memories/query`, {
+		method: 'POST',
+		headers: {
+			Accept: 'application/json',
+			'Content-Type': 'application/json',
+			authorization: `Bearer ${token}`
+		},
+		body: JSON.stringify({
+			content: content
+		})
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.catch((err) => {
+			error = err.detail;
+			console.log(err);
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
+export const deleteMemoryById = async (token: string, id: string) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/memories/${id}`, {
+		method: 'DELETE',
+		headers: {
+			Accept: 'application/json',
+			'Content-Type': 'application/json',
+			authorization: `Bearer ${token}`
+		}
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.then((json) => {
+			return json;
+		})
+		.catch((err) => {
+			error = err.detail;
+
+			console.log(err);
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};

+ 25 - 5
src/lib/components/chat/Settings/Personalization/AddMemoryModal.svelte

@@ -1,17 +1,37 @@
 <script>
-	import { getContext } from 'svelte';
+	import { createEventDispatcher, getContext } from 'svelte';
 
 	import Modal from '$lib/components/common/Modal.svelte';
+	import { addNewMemory } from '$lib/apis/memories';
+	import { toast } from 'svelte-sonner';
+
+	const dispatch = createEventDispatcher();
 
 	export let show;
 
 	const i18n = getContext('i18n');
 
 	let loading = false;
-	let memory = '';
+	let content = '';
+
+	const submitHandler = async () => {
+		loading = true;
+
+		const res = await addNewMemory(localStorage.token, content).catch((error) => {
+			toast.error(error);
+
+			return null;
+		});
+
+		if (res) {
+			console.log(res);
+			toast.success('Memory added successfully');
+			show = false;
+
+			dispatch('save');
+		}
 
-	const submitHandler = () => {
-		console.log('submitHandler');
+		loading = false;
 	};
 </script>
 
@@ -48,7 +68,7 @@
 				>
 					<div class="">
 						<textarea
-							bind:value={memory}
+							bind:value={content}
 							class=" bg-transparent w-full text-sm resize-none rounded-xl p-3 outline outline-1 outline-gray-100 dark:outline-gray-800"
 							rows="3"
 							placeholder={$i18n.t('Enter a detail about yourself for your LLMs to recall')}

+ 53 - 15
src/lib/components/chat/Settings/Personalization/ManageModal.svelte

@@ -7,6 +7,9 @@
 
 	import Modal from '$lib/components/common/Modal.svelte';
 	import AddMemoryModal from './AddMemoryModal.svelte';
+	import { deleteMemoryById, getMemories } from '$lib/apis/memories';
+	import Tooltip from '$lib/components/common/Tooltip.svelte';
+	import { error } from '@sveltejs/kit';
 
 	const i18n = getContext('i18n');
 
@@ -18,7 +21,7 @@
 
 	$: if (show) {
 		(async () => {
-			// chats = await getArchivedChatList(localStorage.token);
+			memories = await getMemories(localStorage.token);
 		})();
 	}
 </script>
@@ -65,20 +68,50 @@
 								</thead>
 								<tbody>
 									{#each memories as memory}
-										<tr class="border-b dark:border-gray-800">
-											<td class="px-3 py-2"> {memory.name} </td>
-											<td class="px-3 py-2 hidden md:flex">
-												{dayjs(memory.created_at).format($i18n.t('MMMM DD, YYYY'))}
+										<tr class="border-b dark:border-gray-800 items-center">
+											<td class="px-3 py-1"> {memory.content} </td>
+											<td class=" px-3 py-1 hidden md:flex h-[2.5rem]">
+												<div class="my-auto">
+													{dayjs(memory.created_at * 1000).format($i18n.t('MMMM DD, YYYY'))}
+												</div>
 											</td>
-											<td class="px-3 py-2 text-right">
-												<button
-													class="text-xs text-gray-500 dark:text-gray-400"
-													on:click={() => {
-														// showMemory(memory);
-													}}
-												>
-													{$i18n.t('View')}
-												</button>
+											<td class="px-3 py-1">
+												<div class="flex justify-end w-full">
+													<Tooltip content="Delete">
+														<button
+															class="self-center w-fit text-sm px-2 py-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
+															on:click={async () => {
+																const res = await deleteMemoryById(
+																	localStorage.token,
+																	memory.id
+																).catch((error) => {
+																	toast.error(error);
+																	return null;
+																});
+
+																if (res) {
+																	toast.success('Memory deleted successfully');
+																	memories = await getMemories(localStorage.token);
+																}
+															}}
+														>
+															<svg
+																xmlns="http://www.w3.org/2000/svg"
+																fill="none"
+																viewBox="0 0 24 24"
+																stroke-width="1.5"
+																stroke="currentColor"
+																class="w-4 h-4"
+															>
+																<path
+																	stroke-linecap="round"
+																	stroke-linejoin="round"
+																	d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0"
+																/>
+															</svg>
+														</button>
+													</Tooltip>
+												</div>
 											</td>
 										</tr>
 									{/each}
@@ -112,4 +145,9 @@
 	</div>
 </Modal>
 
-<AddMemoryModal bind:show={showAddMemoryModal} />
+<AddMemoryModal
+	bind:show={showAddMemoryModal}
+	on:save={async () => {
+		memories = await getMemories(localStorage.token);
+	}}
+/>