Timothy J. Baek 10 months ago
parent
commit
3c599e24e5

+ 13 - 4
backend/apps/webui/routers/memories.py

@@ -43,9 +43,11 @@ async def get_memories(user=Depends(get_verified_user)):
 class AddMemoryForm(BaseModel):
     content: str
 
+
 class MemoryUpdateModel(BaseModel):
     content: Optional[str] = None
 
+
 @router.post("/add", response_model=Optional[MemoryModel])
 async def add_memory(
     request: Request, form_data: AddMemoryForm, user=Depends(get_verified_user)
@@ -64,9 +66,12 @@ async def add_memory(
     return memory
 
 
-@router.post("/{memory_id}", response_model=Optional[MemoryModel])
+@router.post("/{memory_id}/update", response_model=Optional[MemoryModel])
 async def update_memory_by_id(
-    memory_id: str, request: Request, form_data: MemoryUpdateModel, user=Depends(get_verified_user)
+    memory_id: str,
+    request: Request,
+    form_data: MemoryUpdateModel,
+    user=Depends(get_verified_user),
 ):
     memory = Memories.update_memory_by_id(memory_id, form_data.content)
     if memory is None:
@@ -74,12 +79,16 @@ async def update_memory_by_id(
 
     if form_data.content is not None:
         memory_embedding = request.app.state.EMBEDDING_FUNCTION(form_data.content)
-        collection = CHROMA_CLIENT.get_or_create_collection(name=f"user-memory-{user.id}")
+        collection = CHROMA_CLIENT.get_or_create_collection(
+            name=f"user-memory-{user.id}"
+        )
         collection.upsert(
             documents=[form_data.content],
             ids=[memory.id],
             embeddings=[memory_embedding],
-            metadatas=[{"created_at": memory.created_at, "updated_at": memory.updated_at}],
+            metadatas=[
+                {"created_at": memory.created_at, "updated_at": memory.updated_at}
+            ],
         )
 
     return memory

+ 1 - 1
src/lib/apis/memories/index.ts

@@ -62,7 +62,7 @@ export const addNewMemory = async (token: string, content: string) => {
 export const updateMemoryById = async (token: string, id: string, content: string) => {
 	let error = null;
 
-	const res = await fetch(`${WEBUI_API_BASE_URL}/memories/${id}`, {
+	const res = await fetch(`${WEBUI_API_BASE_URL}/memories/${id}/update`, {
 		method: 'POST',
 		headers: {
 			Accept: 'application/json',

+ 2 - 47
src/lib/components/chat/Settings/Personalization/AddMemoryModal.svelte

@@ -8,54 +8,14 @@
 	const dispatch = createEventDispatcher();
 
 	export let show;
-	export let memory = {};
-
-	let showUpdateBtn = false;
-
 	const i18n = getContext('i18n');
 
 	let loading = false;
 	let content = '';
-    let isMemoryLoaded = false;
-
-	$: {
-		if (memory && memory.id && !isMemoryLoaded) {
-			showUpdateBtn = true;
-            content = memory.content;
-			isMemoryLoaded = true;
-		}
-		if (!show) {
-			showUpdateBtn = false;
-			isMemoryLoaded = false;
-			memory = {};
-			content = '';
-		}
-	}
 
 	const submitHandler = async () => {
 		loading = true;
 
-		if (memory && memory.id) {
-			const res = await updateMemoryById(localStorage.token, memory.id, content).catch((error) => {
-				toast.error(error);
-
-				return null;
-			});
-
-			if (res) {
-				console.log(res);
-				toast.success('Memory updated successfully');
-				content = '';
-				show = false;
-				isMemoryLoaded = false;
-				memory = {};
-				dispatch('save');
-			}
-
-			loading = false;
-			return;
-		}
-
 		const res = await addNewMemory(localStorage.token, content).catch((error) => {
 			toast.error(error);
 
@@ -78,7 +38,7 @@
 	<div>
 		<div class=" flex justify-between dark:text-gray-300 px-5 pt-4 pb-2">
 			<div class=" text-lg font-medium self-center">
-				{memory.id ? $i18n.t('Edit Memory') : $i18n.t('Add Memory')}
+				{$i18n.t('Add Memory')}
 			</div>
 			<button
 				class="self-center"
@@ -128,12 +88,7 @@
 							type="submit"
 							disabled={loading}
 						>
-
-							{#if showUpdateBtn}
-								{$i18n.t('Update')}
-							{:else}
-								{$i18n.t('Add')}
-							{/if}
+							{$i18n.t('Add')}
 
 							{#if loading}
 								<div class="ml-2 self-center">

+ 131 - 0
src/lib/components/chat/Settings/Personalization/EditMemoryModal.svelte

@@ -0,0 +1,131 @@
+<script>
+	import { createEventDispatcher, getContext } from 'svelte';
+	import { toast } from 'svelte-sonner';
+
+	import { updateMemoryById } from '$lib/apis/memories';
+
+	import Modal from '$lib/components/common/Modal.svelte';
+
+	const dispatch = createEventDispatcher();
+
+	export let show;
+	export let memory = {};
+
+	const i18n = getContext('i18n');
+
+	let loading = false;
+	let content = '';
+
+	$: if (show) {
+		content = memory.content;
+	}
+
+	const submitHandler = async () => {
+		loading = true;
+
+		const res = await updateMemoryById(localStorage.token, memory.id, content).catch((error) => {
+			toast.error(error);
+
+			return null;
+		});
+
+		if (res) {
+			console.log(res);
+			toast.success('Memory updated successfully');
+			show = false;
+		}
+
+		loading = false;
+	};
+</script>
+
+<Modal bind:show size="sm">
+	<div>
+		<div class=" flex justify-between dark:text-gray-300 px-5 pt-4 pb-2">
+			<div class=" text-lg font-medium self-center">
+				{$i18n.t('Edit Memory')}
+			</div>
+			<button
+				class="self-center"
+				on:click={() => {
+					show = false;
+				}}
+			>
+				<svg
+					xmlns="http://www.w3.org/2000/svg"
+					viewBox="0 0 20 20"
+					fill="currentColor"
+					class="w-5 h-5"
+				>
+					<path
+						d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
+					/>
+				</svg>
+			</button>
+		</div>
+
+		<div class="flex flex-col md:flex-row w-full px-5 pb-4 md:space-x-4 dark:text-gray-200">
+			<div class=" flex flex-col w-full sm:flex-row sm:justify-center sm:space-x-6">
+				<form
+					class="flex flex-col w-full"
+					on:submit|preventDefault={() => {
+						submitHandler();
+					}}
+				>
+					<div class="">
+						<textarea
+							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')}
+						/>
+
+						<div class="text-xs text-gray-500">
+							ⓘ {$i18n.t('Refer to yourself as "User" (e.g., "User is learning Spanish")')}
+						</div>
+					</div>
+
+					<div class="flex justify-end pt-1 text-sm font-medium">
+						<button
+							class=" px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-3xl flex flex-row space-x-1 items-center {loading
+								? ' cursor-not-allowed'
+								: ''}"
+							type="submit"
+							disabled={loading}
+						>
+							{$i18n.t('Update')}
+
+							{#if loading}
+								<div class="ml-2 self-center">
+									<svg
+										class=" w-4 h-4"
+										viewBox="0 0 24 24"
+										fill="currentColor"
+										xmlns="http://www.w3.org/2000/svg"
+										><style>
+											.spinner_ajPY {
+												transform-origin: center;
+												animation: spinner_AtaB 0.75s infinite linear;
+											}
+											@keyframes spinner_AtaB {
+												100% {
+													transform: rotate(360deg);
+												}
+											}
+										</style><path
+											d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z"
+											opacity=".25"
+										/><path
+											d="M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z"
+											class="spinner_ajPY"
+										/></svg
+									>
+								</div>
+							{/if}
+						</button>
+					</div>
+				</form>
+			</div>
+		</div>
+	</div>
+</Modal>

+ 35 - 10
src/lib/components/chat/Settings/Personalization/ManageModal.svelte

@@ -10,6 +10,7 @@
 	import { deleteMemoriesByUserId, deleteMemoryById, getMemories } from '$lib/apis/memories';
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import { error } from '@sveltejs/kit';
+	import EditMemoryModal from './EditMemoryModal.svelte';
 
 	const i18n = getContext('i18n');
 
@@ -17,9 +18,11 @@
 
 	let memories = [];
 	let loading = true;
+
 	let showAddMemoryModal = false;
+	let showEditMemoryModal = false;
 
-	let editMemory = {};
+	let selectedMemory = null;
 
 	$: if (show && memories.length === 0 && loading) {
 		(async () => {
@@ -65,7 +68,9 @@
 								>
 									<tr>
 										<th scope="col" class="px-3 py-2"> {$i18n.t('Name')} </th>
-										<th scope="col" class="px-3 py-2 hidden md:flex"> {$i18n.t('Last Modified')} </th>
+										<th scope="col" class="px-3 py-2 hidden md:flex">
+											{$i18n.t('Last Modified')}
+										</th>
 										<th scope="col" class="px-3 py-2 text-right" />
 									</tr>
 								</thead>
@@ -79,7 +84,9 @@
 											</td>
 											<td class=" px-3 py-1 hidden md:flex h-[2.5rem]">
 												<div class="my-auto whitespace-nowrap">
-													{dayjs(memory.updated_at * 1000).format($i18n.t('MMMM DD, YYYY hh:mm:ss A'))}
+													{dayjs(memory.updated_at * 1000).format(
+														$i18n.t('MMMM DD, YYYY hh:mm:ss A')
+													)}
 												</div>
 											</td>
 											<td class="px-3 py-1">
@@ -88,10 +95,24 @@
 														<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={() => {
-																editMemory = memory;
-																showAddMemoryModal = true;
-															}}>
-															<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 s-FoVA_WMOgxUD"><path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" class="s-FoVA_WMOgxUD"></path></svg>
+																selectedMemory = memory;
+																showEditMemoryModal = true;
+															}}
+														>
+															<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 s-FoVA_WMOgxUD"
+																><path
+																	stroke-linecap="round"
+																	stroke-linejoin="round"
+																	d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125"
+																	class="s-FoVA_WMOgxUD"
+																/></svg
+															>
 														</button>
 													</Tooltip>
 
@@ -172,12 +193,16 @@
 </Modal>
 
 <AddMemoryModal
-	bind:memory={editMemory}
 	bind:show={showAddMemoryModal}
 	on:save={async () => {
 		memories = await getMemories(localStorage.token);
 	}}
-	on:close={() => {
-		editMemory = {};
+/>
+
+<EditMemoryModal
+	bind:show={showEditMemoryModal}
+	memory={selectedMemory}
+	on:save={async () => {
+		memories = await getMemories(localStorage.token);
 	}}
 />