Timothy J. Baek 6 месяцев назад
Родитель
Сommit
076f9fd9c0

+ 77 - 34
src/lib/components/chat/Messages/RateComment.svelte

@@ -3,6 +3,7 @@
 
 	import { createEventDispatcher, onMount, getContext } from 'svelte';
 	import { config, models } from '$lib/stores';
+	import Tags from '$lib/components/common/Tags.svelte';
 
 	const i18n = getContext('i18n');
 
@@ -14,24 +15,28 @@
 	let LIKE_REASONS = [];
 	let DISLIKE_REASONS = [];
 
+	let tags = [];
+
 	function loadReasons() {
 		LIKE_REASONS = [
-			$i18n.t('Accurate information'),
-			$i18n.t('Followed instructions perfectly'),
-			$i18n.t('Showcased creativity'),
-			$i18n.t('Positive attitude'),
-			$i18n.t('Attention to detail'),
-			$i18n.t('Thorough explanation'),
-			$i18n.t('Other')
+			'accurate_information',
+			'followed_instructions_perfectly',
+			'showcased_creativity',
+			'positive_attitude',
+			'attention_to_detail',
+			'thorough_explanation',
+			'other'
 		];
 
 		DISLIKE_REASONS = [
-			$i18n.t("Don't like the style"),
-			$i18n.t('Not factually correct'),
-			$i18n.t("Didn't fully follow instructions"),
-			$i18n.t("Refused when it shouldn't have"),
-			$i18n.t('Being lazy'),
-			$i18n.t('Other')
+			'dont_like_the_style',
+			'too_verbose',
+			'not_helpful',
+			'not_factually_correct',
+			'didnt_fully_follow_instructions',
+			'refused_when_it_shouldnt_have',
+			'being_lazy',
+			'other'
 		];
 	}
 
@@ -50,6 +55,9 @@
 	onMount(() => {
 		selectedReason = message?.annotation?.reason ?? '';
 		comment = message?.annotation?.comment ?? '';
+		tags = (message?.annotation?.tags ?? []).map((tag) => ({
+			name: tag
+		}));
 
 		if (message?.arena) {
 			selectedModel = $models.find((m) => m.id === message.selectedModelId);
@@ -66,14 +74,15 @@
 	const saveHandler = () => {
 		console.log('saveHandler');
 
-		if (!selectedReason) {
-			toast.error($i18n.t('Please select a reason'));
-			return;
-		}
+		// if (!selectedReason) {
+		// 	toast.error($i18n.t('Please select a reason'));
+		// 	return;
+		// }
 
 		dispatch('save', {
 			reason: selectedReason,
-			comment: comment
+			comment: comment,
+			tags: tags
 		});
 
 		toast.success($i18n.t('Thanks for your feedback!'));
@@ -82,7 +91,7 @@
 </script>
 
 {#if message?.arena}
-	<div class="text-xs font-medium translate-y-1.5">
+	<div class="text-xs font-medium pt-1.5 -mb-0.5">
 		{$i18n.t('This response was generated by "{{model}}"', {
 			model: selectedModel ? (selectedModel?.name ?? selectedModel.id) : message.selectedModelId
 		})}
@@ -115,10 +124,10 @@
 	</div>
 
 	{#if reasons.length > 0}
-		<div class="flex flex-wrap gap-2 text-sm mt-2.5">
+		<div class="flex flex-wrap gap-1.5 text-sm mt-2.5">
 			{#each reasons as reason}
 				<button
-					class="px-3.5 py-1 border border-gray-50 dark:border-gray-850 hover:bg-gray-100 dark:hover:bg-gray-850 {selectedReason ===
+					class="px-3 py-0.5 border border-gray-50 dark:border-gray-850 hover:bg-gray-100 dark:hover:bg-gray-850 {selectedReason ===
 					reason
 						? 'bg-gray-200 dark:bg-gray-800'
 						: ''} transition rounded-lg"
@@ -126,7 +135,37 @@
 						selectedReason = reason;
 					}}
 				>
-					{reason}
+					{#if reason === 'accurate_information'}
+						{$i18n.t('Accurate information')}
+					{:else if reason === 'followed_instructions_perfectly'}
+						{$i18n.t('Followed instructions perfectly')}
+					{:else if reason === 'showcased_creativity'}
+						{$i18n.t('Showcased creativity')}
+					{:else if reason === 'positive_attitude'}
+						{$i18n.t('Positive attitude')}
+					{:else if reason === 'attention_to_detail'}
+						{$i18n.t('Attention to detail')}
+					{:else if reason === 'thorough_explanation'}
+						{$i18n.t('Thorough explanation')}
+					{:else if reason === 'dont_like_the_style'}
+						{$i18n.t("Don't like the style")}
+					{:else if reason === 'too_verbose'}
+						{$i18n.t('Too verbose')}
+					{:else if reason === 'not_helpful'}
+						{$i18n.t('Not helpful')}
+					{:else if reason === 'not_factually_correct'}
+						{$i18n.t('Not factually correct')}
+					{:else if reason === 'didnt_fully_follow_instructions'}
+						{$i18n.t("Didn't fully follow instructions")}
+					{:else if reason === 'refused_when_it_shouldnt_have'}
+						{$i18n.t("Refused when it shouldn't have")}
+					{:else if reason === 'being_lazy'}
+						{$i18n.t('Being lazy')}
+					{:else if reason === 'other'}
+						{$i18n.t('Other')}
+					{:else}
+						{reason}
+					{/if}
 				</button>
 			{/each}
 		</div>
@@ -137,22 +176,26 @@
 			bind:value={comment}
 			class="w-full text-sm px-1 py-2 bg-transparent outline-none resize-none rounded-xl"
 			placeholder={$i18n.t('Feel free to add specific details')}
-			rows="2"
+			rows="3"
 		/>
 	</div>
 
-	<div class="mt-2 gap-1.5 flex justify-end">
-		<!-- {#if $config?.features.enable_community_sharing && selectedModel}
-			<button
-				class=" self-center px-3.5 py-2 rounded-xl text-sm font-medium bg-gray-50 hover:bg-gray-100 text-gray-800 dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-white transition"
-				type="button"
-				on:click={() => {
-					show = false;
+	<div class="mt-2 gap-1.5 flex justify-between">
+		<div class="flex items-end group">
+			<Tags
+				{tags}
+				on:delete={(e) => {
+					tags = tags.filter(
+						(tag) =>
+							tag.name.replaceAll(' ', '_').toLowerCase() !==
+							e.detail.replaceAll(' ', '_').toLowerCase()
+					);
 				}}
-			>
-				{$i18n.t('Share to OpenWebUI Community')}
-			</button>
-		{/if} -->
+				on:add={(e) => {
+					tags = [...tags, { name: e.detail }];
+				}}
+			/>
+		</div>
 
 		<button
 			class=" bg-emerald-700 hover:bg-emerald-800 transition text-white text-sm font-medium rounded-xl px-3.5 py-1.5"

+ 22 - 1
src/lib/components/chat/Messages/ResponseMessage.svelte

@@ -19,7 +19,8 @@
 		extractSentencesForAudio,
 		cleanText,
 		getMessageContentParts,
-		sanitizeResponseContent
+		sanitizeResponseContent,
+		createMessagesList
 	} from '$lib/utils';
 	import { WEBUI_BASE_URL } from '$lib/constants';
 
@@ -42,6 +43,7 @@
 	import ContentRenderer from './ContentRenderer.svelte';
 	import { createNewFeedback, getFeedbackById, updateFeedbackById } from '$lib/apis/evaluations';
 	import { getChatById } from '$lib/apis/chats';
+	import { generateTags } from '$lib/apis';
 
 	interface MessageType {
 		id: string;
@@ -355,6 +357,24 @@
 			return;
 		}
 
+		if (!annotation) {
+			const messages = createMessagesList(history, message.id);
+			const tags = await generateTags(
+				localStorage.token,
+				message?.selectedModelId ?? message.model,
+				messages,
+				chatId
+			).catch((error) => {
+				console.error(error);
+				return [];
+			});
+			console.log(tags);
+
+			if (tags) {
+				updatedMessage.annotation.tags = tags;
+			}
+		}
+
 		let feedbackItem = {
 			type: 'rating',
 			data: {
@@ -1183,6 +1203,7 @@
 							bind:show={showRateComment}
 							on:save={async (e) => {
 								await feedbackHandler(null, {
+									tags: e.detail.tags,
 									comment: e.detail.comment,
 									reason: e.detail.reason
 								});

+ 1 - 1
src/lib/components/chat/Messages/UserMessage.svelte

@@ -142,7 +142,7 @@
 
 			{#if edit === true}
 				<div class=" w-full bg-gray-50 dark:bg-gray-800 rounded-3xl px-5 py-3 mb-2">
-					<div class="max-h-[25dvh] overflow-auto">
+					<div class="max-h-96 overflow-auto">
 						<textarea
 							id="message-edit-{message.id}"
 							bind:this={messageEditTextAreaElement}

+ 9 - 1
src/lib/components/chat/TagChatModal.svelte

@@ -15,6 +15,14 @@
 
 <Modal bind:show size="xs">
 	<div class="px-4 pt-4 pb-5 w-full flex flex-col justify-center">
-		<Tags {tags} {deleteTag} {addTag} />
+		<Tags
+			{tags}
+			on:delete={(e) => {
+				deleteTag(e.detail);
+			}}
+			on:add={(e) => {
+				addTag(e.detail);
+			}}
+		/>
 	</div>
 </Modal>

+ 9 - 1
src/lib/components/chat/Tags.svelte

@@ -71,4 +71,12 @@
 	});
 </script>
 
-<Tags {tags} {deleteTag} {addTag} />
+<Tags
+	{tags}
+	on:delete={(e) => {
+		deleteTag(e.detail);
+	}}
+	on:add={(e) => {
+		addTag(e.detail);
+	}}
+/>

+ 4 - 6
src/lib/components/common/Tags.svelte

@@ -1,28 +1,26 @@
 <script lang="ts">
 	import TagInput from './Tags/TagInput.svelte';
 	import TagList from './Tags/TagList.svelte';
-	import { getContext } from 'svelte';
+	import { getContext, createEventDispatcher } from 'svelte';
+	const dispatch = createEventDispatcher();
 
 	const i18n = getContext('i18n');
 
 	export let tags = [];
-
-	export let deleteTag: Function;
-	export let addTag: Function;
 </script>
 
 <div class="flex flex-row flex-wrap gap-1 line-clamp-1">
 	<TagList
 		{tags}
 		on:delete={(e) => {
-			deleteTag(e.detail);
+			dispatch('delete', e.detail);
 		}}
 	/>
 
 	<TagInput
 		label={tags.length == 0 ? $i18n.t('Add Tags') : ''}
 		on:add={(e) => {
-			addTag(e.detail);
+			dispatch('add', e.detail);
 		}}
 	/>
 </div>

+ 2 - 2
src/lib/components/common/Tags/TagList.svelte

@@ -11,12 +11,12 @@
 {#each tags as tag}
 	<Tooltip content={tag.name}>
 		<div
-			class="relative group px-1.5 py-[0.2px] gap-0.5 flex justify-between h-fit max-h-fit w-fit items-center rounded-full bg-gray-500/20 text-gray-700 dark:text-gray-200 transition cursor-pointer"
+			class="relative group/tags px-1.5 py-[0.2px] gap-0.5 flex justify-between h-fit max-h-fit w-fit items-center rounded-full bg-gray-500/20 text-gray-700 dark:text-gray-200 transition cursor-pointer"
 		>
 			<div class=" text-[0.7rem] font-medium self-center line-clamp-1 w-fit">
 				{tag.name}
 			</div>
-			<div class="absolute invisible right-0.5 group-hover:visible transition">
+			<div class="absolute invisible right-0.5 group-hover/tags:visible transition">
 				<button
 					class="rounded-full border bg-white dark:bg-gray-700 h-full flex self-center cursor-pointer"
 					on:click={() => {

+ 4 - 3
src/routes/(app)/workspace/models/create/+page.svelte

@@ -671,11 +671,12 @@
 			<div class="mt-2">
 				<Tags
 					tags={info?.meta?.tags ?? []}
-					deleteTag={(tagName) => {
+					on:delete={(e) => {
+						const tagName = e.detail;
 						info.meta.tags = info.meta.tags.filter((tag) => tag.name !== tagName);
 					}}
-					addTag={(tagName) => {
-						console.log(tagName);
+					on:add={(e) => {
+						const tagName = e.detail;
 						if (!(info?.meta?.tags ?? null)) {
 							info.meta.tags = [{ name: tagName }];
 						} else {

+ 4 - 3
src/routes/(app)/workspace/models/edit/+page.svelte

@@ -618,11 +618,12 @@
 				<div class="mt-2">
 					<Tags
 						tags={info?.meta?.tags ?? []}
-						deleteTag={(tagName) => {
+						on:delete={(e) => {
+							const tagName = e.detail;
 							info.meta.tags = info.meta.tags.filter((tag) => tag.name !== tagName);
 						}}
-						addTag={(tagName) => {
-							console.log(tagName);
+						on:add={(e) => {
+							const tagName = e.detail;
 							if (!(info?.meta?.tags ?? null)) {
 								info.meta.tags = [{ name: tagName }];
 							} else {