Spaces:
Runtime error
Runtime error
| <script lang="ts"> | |
| import { toast } from "svelte-sonner"; | |
| import { createEventDispatcher, onMount, getContext } from "svelte"; | |
| import { config, models, tags as _tags } from "$lib/stores"; | |
| import Tags from "$lib/components/common/Tags.svelte"; | |
| import XMark from "$lib/components/icons/XMark.svelte"; | |
| import ChevronRight from "$lib/components/icons/ChevronRight.svelte"; | |
| const i18n = getContext("i18n"); | |
| const dispatch = createEventDispatcher(); | |
| export let message; | |
| export let show = false; | |
| let LIKE_REASONS = [ | |
| "accurate_information", | |
| "followed_instructions_perfectly", | |
| "showcased_creativity", | |
| "positive_attitude", | |
| "attention_to_detail", | |
| "thorough_explanation", | |
| "other", | |
| ]; | |
| let DISLIKE_REASONS = [ | |
| "dont_like_the_style", | |
| "too_verbose", | |
| "not_helpful", | |
| "not_factually_correct", | |
| "didnt_fully_follow_instructions", | |
| "refused_when_it_shouldnt_have", | |
| "being_lazy", | |
| "other", | |
| ]; | |
| let tags = []; | |
| let reasons = []; | |
| let selectedReason = null; | |
| let comment = ""; | |
| let detailedRating = null; | |
| let selectedModel = null; | |
| $: if (message?.annotation?.rating === 1) { | |
| reasons = LIKE_REASONS; | |
| } else if (message?.annotation?.rating === -1) { | |
| reasons = DISLIKE_REASONS; | |
| } | |
| $: if (message) { | |
| init(); | |
| } | |
| const init = () => { | |
| if (!selectedReason) { | |
| selectedReason = message?.annotation?.reason ?? ""; | |
| } | |
| if (!comment) { | |
| comment = message?.annotation?.comment ?? ""; | |
| } | |
| tags = (message?.annotation?.tags ?? []).map((tag) => ({ | |
| name: tag, | |
| })); | |
| if (!detailedRating) { | |
| detailedRating = message?.annotation?.details?.rating ?? null; | |
| } | |
| }; | |
| onMount(() => { | |
| if (message?.arena) { | |
| selectedModel = $models.find( | |
| (m) => m.id === message.selectedModelId, | |
| ); | |
| toast.success( | |
| $i18n.t('This response was generated by "{{model}}"', { | |
| model: selectedModel | |
| ? (selectedModel?.name ?? selectedModel.id) | |
| : message.selectedModelId, | |
| }), | |
| ); | |
| } | |
| }); | |
| const saveHandler = () => { | |
| console.log("saveHandler"); | |
| // if (!selectedReason) { | |
| // toast.error($i18n.t('Please select a reason')); | |
| // return; | |
| // } | |
| dispatch("save", { | |
| reason: selectedReason, | |
| comment: comment, | |
| tags: tags.map((tag) => tag.name), | |
| details: { | |
| rating: detailedRating, | |
| }, | |
| }); | |
| toast.success($i18n.t("Thanks for your feedback!")); | |
| show = false; | |
| }; | |
| </script> | |
| {#if message?.arena} | |
| <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, | |
| })} | |
| </div> | |
| {/if} | |
| <div | |
| class=" my-2.5 rounded-xl px-4 py-3 border border-gray-100/30 dark:border-gray-850/30" | |
| id="message-feedback-{message.id}" | |
| > | |
| <div class="flex justify-between items-center"> | |
| <div class="text-sm font-medium"> | |
| {$i18n.t("How would you rate this response?")} | |
| </div> | |
| <!-- <div class=" text-sm">{$i18n.t('Tell us more:')}</div> --> | |
| <button | |
| aria-label={$i18n.t("Close feedback")} | |
| on:click={() => { | |
| show = false; | |
| }} | |
| > | |
| <XMark className={"size-4"} /> | |
| </button> | |
| </div> | |
| <div class="w-full flex justify-center"> | |
| <div class=" relative w-fit overflow-x-auto scrollbar-none"> | |
| <div class="mt-1.5 w-fit flex gap-1 pb-2"> | |
| <!-- 1-10 scale --> | |
| {#each Array.from( { length: 10 }, ).map((_, i) => i + 1) as rating} | |
| <button | |
| aria-label={$i18n.t("Rate {{rating}} out of 10", { | |
| rating, | |
| })} | |
| class="size-7 text-sm border border-gray-100/30 dark:border-gray-850/30 hover:bg-gray-50 dark:hover:bg-gray-850 {detailedRating === | |
| rating | |
| ? 'bg-gray-100 dark:bg-gray-800' | |
| : ''} transition rounded-full disabled:cursor-not-allowed disabled:text-gray-500 disabled:bg-white dark:disabled:bg-gray-900" | |
| on:click={() => { | |
| detailedRating = rating; | |
| }} | |
| disabled={message?.annotation?.rating === -1 | |
| ? rating > 5 | |
| : rating < 6} | |
| > | |
| {rating} | |
| </button> | |
| {/each} | |
| </div> | |
| <div | |
| class="sticky top-0 bottom-0 left-0 right-0 flex justify-between text-xs" | |
| > | |
| <div> | |
| 1 - {$i18n.t("Awful")} | |
| </div> | |
| <div> | |
| 10 - {$i18n.t("Amazing")} | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div> | |
| {#if reasons.length > 0} | |
| <div class="text-sm mt-1.5 font-medium">{$i18n.t("Why?")}</div> | |
| <div class="flex flex-wrap gap-1.5 text-sm mt-1.5"> | |
| {#each reasons as reason} | |
| <button | |
| class="px-3 py-0.5 border border-gray-100/30 dark:border-gray-850/30 hover:bg-gray-50 dark:hover:bg-gray-850 {selectedReason === | |
| reason | |
| ? 'bg-gray-100 dark:bg-gray-800' | |
| : ''} transition rounded-xl" | |
| on:click={() => { | |
| selectedReason = 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> | |
| {/if} | |
| </div> | |
| <div class="mt-2"> | |
| <textarea | |
| bind:value={comment} | |
| class="w-full text-sm px-1 py-2 bg-transparent outline-hidden resize-none rounded-xl" | |
| placeholder={$i18n.t("Feel free to add specific details")} | |
| aria-label={$i18n.t("Additional feedback comments")} | |
| rows="3" | |
| /> | |
| </div> | |
| <div class="mt-2 gap-1.5 flex justify-between"> | |
| <div class="flex items-end group"> | |
| <Tags | |
| {tags} | |
| suggestionTags={$_tags ?? []} | |
| on:delete={(e) => { | |
| tags = tags.filter( | |
| (tag) => | |
| tag.name.replaceAll(" ", "_").toLowerCase() !== | |
| e.detail.replaceAll(" ", "_").toLowerCase(), | |
| ); | |
| }} | |
| on:add={(e) => { | |
| tags = [...tags, { name: e.detail }]; | |
| }} | |
| /> | |
| </div> | |
| <button | |
| class="px-3.5 py-1.5 text-sm font-medium bg-black hover:bg-gray-900 text-white dark:bg-white dark:text-black dark:hover:bg-gray-100 transition rounded-full" | |
| on:click={() => { | |
| saveHandler(); | |
| }} | |
| > | |
| {$i18n.t("Save")} | |
| </button> | |
| </div> | |
| {#if $config?.features.enable_community_sharing && message?.model} | |
| <div | |
| class="mt-3 pt-3 border-t border-gray-100/30 dark:border-gray-850/30" | |
| > | |
| <a | |
| href={`https://rexpro-ai.rexpro.com/models?q=${encodeURIComponent(message.model)}`} | |
| target="_blank" | |
| class="flex cursor-pointer items-center justify-between hover:bg-gray-50 dark:hover:bg-gray-850 w-full px-3 py-2 rounded-xl transition" | |
| > | |
| <div class="self-center"> | |
| <div class="text-sm font-medium"> | |
| {$i18n.t("Leave a public review for {{modelName}}", { | |
| modelName: message.model, | |
| })} | |
| </div> | |
| <div class="text-xs text-gray-500"> | |
| {$i18n.t("Help the community discover great models")} | |
| </div> | |
| </div> | |
| <ChevronRight className="size-4" /> | |
| </a> | |
| </div> | |
| {/if} | |
| </div> | |