forked from open-webui/open-webui
		
	feat: editable prompt suggestions integration
This commit is contained in:
		
							parent
							
								
									4e1b52e91b
								
							
						
					
					
						commit
						c4a039326f
					
				
					 6 changed files with 172 additions and 52 deletions
				
			
		| 
						 | 
				
			
			@ -13,7 +13,7 @@
 | 
			
		|||
				}}
 | 
			
		||||
			>
 | 
			
		||||
				<div class="flex flex-col text-left self-center">
 | 
			
		||||
					{#if prompt.title}
 | 
			
		||||
					{#if prompt.title && prompt.title[0] !== ''}
 | 
			
		||||
						<div class="text-sm font-medium dark:text-gray-300">{prompt.title[0]}</div>
 | 
			
		||||
						<div class="text-sm text-gray-500">{prompt.title[1]}</div>
 | 
			
		||||
					{:else}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,6 +34,8 @@
 | 
			
		|||
		updateOpenAIUrl
 | 
			
		||||
	} from '$lib/apis/openai';
 | 
			
		||||
	import { resetVectorDB } from '$lib/apis/rag';
 | 
			
		||||
	import { setDefaultPromptSuggestions } from '$lib/apis/configs';
 | 
			
		||||
	import { getBackendConfig } from '$lib/apis';
 | 
			
		||||
 | 
			
		||||
	export let show = false;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -99,6 +101,9 @@
 | 
			
		|||
	let OPENAI_API_KEY = '';
 | 
			
		||||
	let OPENAI_API_BASE_URL = '';
 | 
			
		||||
 | 
			
		||||
	// Interface
 | 
			
		||||
	let promptSuggestions = [];
 | 
			
		||||
 | 
			
		||||
	// Addons
 | 
			
		||||
	let titleAutoGenerate = true;
 | 
			
		||||
	let speechAutoSend = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -191,6 +196,11 @@
 | 
			
		|||
		await models.set(await getModels());
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	const updateInterfaceHandler = async () => {
 | 
			
		||||
		promptSuggestions = await setDefaultPromptSuggestions(localStorage.token, promptSuggestions);
 | 
			
		||||
		await config.set(await getBackendConfig());
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	const toggleTheme = async () => {
 | 
			
		||||
		if (theme === 'dark') {
 | 
			
		||||
			theme = 'light';
 | 
			
		||||
| 
						 | 
				
			
			@ -577,6 +587,7 @@
 | 
			
		|||
			API_BASE_URL = await getOllamaAPIUrl(localStorage.token);
 | 
			
		||||
			OPENAI_API_BASE_URL = await getOpenAIUrl(localStorage.token);
 | 
			
		||||
			OPENAI_API_KEY = await getOpenAIKey(localStorage.token);
 | 
			
		||||
			promptSuggestions = $config?.default_prompt_suggestions;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		let settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
 | 
			
		||||
| 
						 | 
				
			
			@ -745,6 +756,32 @@
 | 
			
		|||
						</div>
 | 
			
		||||
						<div class=" self-center">External</div>
 | 
			
		||||
					</button>
 | 
			
		||||
 | 
			
		||||
					<button
 | 
			
		||||
						class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
 | 
			
		||||
						'interface'
 | 
			
		||||
							? 'bg-gray-200 dark:bg-gray-700'
 | 
			
		||||
							: ' hover:bg-gray-300 dark:hover:bg-gray-800'}"
 | 
			
		||||
						on:click={() => {
 | 
			
		||||
							selectedTab = 'interface';
 | 
			
		||||
						}}
 | 
			
		||||
					>
 | 
			
		||||
						<div class=" self-center mr-2">
 | 
			
		||||
							<svg
 | 
			
		||||
								xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
								viewBox="0 0 16 16"
 | 
			
		||||
								fill="currentColor"
 | 
			
		||||
								class="w-4 h-4"
 | 
			
		||||
							>
 | 
			
		||||
								<path
 | 
			
		||||
									fill-rule="evenodd"
 | 
			
		||||
									d="M2 4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V4Zm10.5 5.707a.5.5 0 0 0-.146-.353l-1-1a.5.5 0 0 0-.708 0L9.354 9.646a.5.5 0 0 1-.708 0L6.354 7.354a.5.5 0 0 0-.708 0l-2 2a.5.5 0 0 0-.146.353V12a.5.5 0 0 0 .5.5h8a.5.5 0 0 0 .5-.5V9.707ZM12 5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"
 | 
			
		||||
									clip-rule="evenodd"
 | 
			
		||||
								/>
 | 
			
		||||
							</svg>
 | 
			
		||||
						</div>
 | 
			
		||||
						<div class=" self-center">Interface</div>
 | 
			
		||||
					</button>
 | 
			
		||||
				{/if}
 | 
			
		||||
 | 
			
		||||
				<button
 | 
			
		||||
| 
						 | 
				
			
			@ -797,34 +834,6 @@
 | 
			
		|||
					<div class=" self-center">Chats</div>
 | 
			
		||||
				</button>
 | 
			
		||||
 | 
			
		||||
				{#if !$config || ($config && !$config.auth)}
 | 
			
		||||
					<button
 | 
			
		||||
						class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
 | 
			
		||||
						'auth'
 | 
			
		||||
							? 'bg-gray-200 dark:bg-gray-700'
 | 
			
		||||
							: ' hover:bg-gray-300 dark:hover:bg-gray-800'}"
 | 
			
		||||
						on:click={() => {
 | 
			
		||||
							selectedTab = 'auth';
 | 
			
		||||
						}}
 | 
			
		||||
					>
 | 
			
		||||
						<div class=" self-center mr-2">
 | 
			
		||||
							<svg
 | 
			
		||||
								xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
								viewBox="0 0 24 24"
 | 
			
		||||
								fill="currentColor"
 | 
			
		||||
								class="w-4 h-4"
 | 
			
		||||
							>
 | 
			
		||||
								<path
 | 
			
		||||
									fill-rule="evenodd"
 | 
			
		||||
									d="M12.516 2.17a.75.75 0 00-1.032 0 11.209 11.209 0 01-7.877 3.08.75.75 0 00-.722.515A12.74 12.74 0 002.25 9.75c0 5.942 4.064 10.933 9.563 12.348a.749.749 0 00.374 0c5.499-1.415 9.563-6.406 9.563-12.348 0-1.39-.223-2.73-.635-3.985a.75.75 0 00-.722-.516l-.143.001c-2.996 0-5.717-1.17-7.734-3.08zm3.094 8.016a.75.75 0 10-1.22-.872l-3.236 4.53L9.53 12.22a.75.75 0 00-1.06 1.06l2.25 2.25a.75.75 0 001.14-.094l3.75-5.25z"
 | 
			
		||||
									clip-rule="evenodd"
 | 
			
		||||
								/>
 | 
			
		||||
							</svg>
 | 
			
		||||
						</div>
 | 
			
		||||
						<div class=" self-center">Authentication</div>
 | 
			
		||||
					</button>
 | 
			
		||||
				{/if}
 | 
			
		||||
 | 
			
		||||
				<button
 | 
			
		||||
					class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
 | 
			
		||||
					'account'
 | 
			
		||||
| 
						 | 
				
			
			@ -877,7 +886,7 @@
 | 
			
		|||
					<div class=" self-center">About</div>
 | 
			
		||||
				</button>
 | 
			
		||||
			</div>
 | 
			
		||||
			<div class="flex-1 md:min-h-[340px]">
 | 
			
		||||
			<div class="flex-1 md:min-h-[380px]">
 | 
			
		||||
				{#if selectedTab === 'general'}
 | 
			
		||||
					<div class="flex flex-col space-y-3">
 | 
			
		||||
						<div>
 | 
			
		||||
| 
						 | 
				
			
			@ -1048,7 +1057,7 @@
 | 
			
		|||
					</div>
 | 
			
		||||
				{:else if selectedTab === 'advanced'}
 | 
			
		||||
					<div class="flex flex-col h-full justify-between text-sm">
 | 
			
		||||
						<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-72">
 | 
			
		||||
						<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-80">
 | 
			
		||||
							<div class=" text-sm font-medium">Parameters</div>
 | 
			
		||||
 | 
			
		||||
							<Advanced bind:options />
 | 
			
		||||
| 
						 | 
				
			
			@ -1483,6 +1492,103 @@
 | 
			
		|||
							</div>
 | 
			
		||||
						</div>
 | 
			
		||||
 | 
			
		||||
						<div class="flex justify-end pt-3 text-sm font-medium">
 | 
			
		||||
							<button
 | 
			
		||||
								class=" px-4 py-2 bg-emerald-600 hover:bg-emerald-700 text-gray-100 transition rounded"
 | 
			
		||||
								type="submit"
 | 
			
		||||
							>
 | 
			
		||||
								Save
 | 
			
		||||
							</button>
 | 
			
		||||
						</div>
 | 
			
		||||
					</form>
 | 
			
		||||
				{:else if selectedTab === 'interface'}
 | 
			
		||||
					<form
 | 
			
		||||
						class="flex flex-col h-full justify-between space-y-3 text-sm"
 | 
			
		||||
						on:submit|preventDefault={() => {
 | 
			
		||||
							updateInterfaceHandler();
 | 
			
		||||
							show = false;
 | 
			
		||||
						}}
 | 
			
		||||
					>
 | 
			
		||||
						<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-80">
 | 
			
		||||
							<div class="flex w-full justify-between mb-2">
 | 
			
		||||
								<div class=" self-center text-sm font-semibold">Default Prompt Suggestions</div>
 | 
			
		||||
 | 
			
		||||
								<button
 | 
			
		||||
									class="p-1 px-3 text-xs flex rounded transition"
 | 
			
		||||
									type="button"
 | 
			
		||||
									on:click={() => {
 | 
			
		||||
										if (promptSuggestions.length === 0 || promptSuggestions.at(-1).content !== '') {
 | 
			
		||||
											promptSuggestions = [...promptSuggestions, { content: '', title: ['', ''] }];
 | 
			
		||||
										}
 | 
			
		||||
									}}
 | 
			
		||||
								>
 | 
			
		||||
									<svg
 | 
			
		||||
										xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
										viewBox="0 0 20 20"
 | 
			
		||||
										fill="currentColor"
 | 
			
		||||
										class="w-4 h-4"
 | 
			
		||||
									>
 | 
			
		||||
										<path
 | 
			
		||||
											d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z"
 | 
			
		||||
										/>
 | 
			
		||||
									</svg>
 | 
			
		||||
								</button>
 | 
			
		||||
							</div>
 | 
			
		||||
							<div class="flex flex-col space-y-1">
 | 
			
		||||
								{#each promptSuggestions as prompt, promptIdx}
 | 
			
		||||
									<div class=" flex border dark:border-gray-600 rounded-lg">
 | 
			
		||||
										<div class="flex flex-col flex-1">
 | 
			
		||||
											<div class="flex border-b dark:border-gray-600 w-full">
 | 
			
		||||
												<input
 | 
			
		||||
													class="px-3 py-1.5 text-xs w-full bg-transparent outline-none border-r dark:border-gray-600"
 | 
			
		||||
													placeholder="Title (e.g. Tell me a fun fact)"
 | 
			
		||||
													bind:value={prompt.title[0]}
 | 
			
		||||
												/>
 | 
			
		||||
 | 
			
		||||
												<input
 | 
			
		||||
													class="px-3 py-1.5 text-xs w-full bg-transparent outline-none border-r dark:border-gray-600"
 | 
			
		||||
													placeholder="Subtitle (e.g. about the Roman Empire)"
 | 
			
		||||
													bind:value={prompt.title[1]}
 | 
			
		||||
												/>
 | 
			
		||||
											</div>
 | 
			
		||||
 | 
			
		||||
											<input
 | 
			
		||||
												class="px-3 py-1.5 text-xs w-full bg-transparent outline-none border-r dark:border-gray-600"
 | 
			
		||||
												placeholder="Prompt (e.g. Tell me a fun fact about the Roman Empire)"
 | 
			
		||||
												bind:value={prompt.content}
 | 
			
		||||
											/>
 | 
			
		||||
										</div>
 | 
			
		||||
 | 
			
		||||
										<button
 | 
			
		||||
											class="px-2"
 | 
			
		||||
											type="button"
 | 
			
		||||
											on:click={() => {
 | 
			
		||||
												promptSuggestions.splice(promptIdx, 1);
 | 
			
		||||
												promptSuggestions = promptSuggestions;
 | 
			
		||||
											}}
 | 
			
		||||
										>
 | 
			
		||||
											<svg
 | 
			
		||||
												xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
												viewBox="0 0 20 20"
 | 
			
		||||
												fill="currentColor"
 | 
			
		||||
												class="w-4 h-4"
 | 
			
		||||
											>
 | 
			
		||||
												<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>
 | 
			
		||||
								{/each}
 | 
			
		||||
							</div>
 | 
			
		||||
 | 
			
		||||
							{#if promptSuggestions.length > 0}
 | 
			
		||||
								<div class="text-xs text-left w-full mt-2">
 | 
			
		||||
									Adjusting these settings will apply changes universally to all users.
 | 
			
		||||
								</div>
 | 
			
		||||
							{/if}
 | 
			
		||||
						</div>
 | 
			
		||||
 | 
			
		||||
						<div class="flex justify-end pt-3 text-sm font-medium">
 | 
			
		||||
							<button
 | 
			
		||||
								class=" px-4 py-2 bg-emerald-600 hover:bg-emerald-700 text-gray-100 transition rounded"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue