feat: model tag support

This commit is contained in:
Timothy J. Baek 2024-05-31 12:08:25 -07:00
parent 0cf9b07ec2
commit eca20b1b2c
7 changed files with 155 additions and 54 deletions

View File

@ -39,7 +39,7 @@
{#if !dismissed} {#if !dismissed}
{#if mounted} {#if mounted}
<div <div
class=" top-0 left-0 right-0 p-2 mx-4 px-3 flex justify-center items-center relative rounded-xl border border-gray-100 dark:border-gray-850 text-gray-800 dark:text-gary-100 bg-white dark:bg-gray-900 backdrop-blur-xl z-40" class=" top-0 left-0 right-0 p-2 mx-4 px-3 flex justify-center items-center relative rounded-xl border border-gray-50 dark:border-gray-850 text-gray-800 dark:text-gary-100 bg-white dark:bg-gray-900 backdrop-blur-xl z-40"
transition:fade={{ delay: 100, duration: 300 }} transition:fade={{ delay: 100, duration: 300 }}
> >
<div class=" flex flex-col md:flex-row md:items-center flex-1 text-sm w-fit gap-1.5"> <div class=" flex flex-col md:flex-row md:items-center flex-1 text-sm w-fit gap-1.5">

View File

@ -14,6 +14,7 @@
onOpenChange={(state) => { onOpenChange={(state) => {
dispatch('change', state); dispatch('change', state);
}} }}
typeahead={false}
> >
<DropdownMenu.Trigger> <DropdownMenu.Trigger>
<slot /> <slot />

View File

@ -11,7 +11,7 @@
export let addTag: Function; export let addTag: Function;
</script> </script>
<div class="flex flex-row flex-wrap gap-0.5 line-clamp-1"> <div class="flex flex-row flex-wrap gap-1 line-clamp-1">
<TagList <TagList
{tags} {tags}
on:delete={(e) => { on:delete={(e) => {

View File

@ -22,26 +22,12 @@
}; };
</script> </script>
<div class="flex space-x-1 pl-1.5"> <div class="flex {showTagInput ? 'flex-row-reverse' : ''}">
{#if showTagInput} {#if showTagInput}
<div class="flex items-center"> <div class="flex items-center">
<button type="button" on:click={addTagHandler}>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-3 h-3"
>
<path
fill-rule="evenodd"
d="M12.416 3.376a.75.75 0 0 1 .208 1.04l-5 7.5a.75.75 0 0 1-1.154.114l-3-3a.75.75 0 0 1 1.06-1.06l2.353 2.353 4.493-6.74a.75.75 0 0 1 1.04-.207Z"
clip-rule="evenodd"
/>
</svg>
</button>
<input <input
bind:value={tagName} bind:value={tagName}
class=" pl-2 cursor-pointer self-center text-xs h-fit bg-transparent outline-none line-clamp-1 w-[5.5rem]" class=" px-2 cursor-pointer self-center text-xs h-fit bg-transparent outline-none line-clamp-1 w-[5.5rem]"
placeholder={$i18n.t('Add a tag')} placeholder={$i18n.t('Add a tag')}
list="tagOptions" list="tagOptions"
on:keydown={(event) => { on:keydown={(event) => {
@ -55,11 +41,27 @@
<option value={tag.name} /> <option value={tag.name} />
{/each} {/each}
</datalist> </datalist>
<button type="button" on:click={addTagHandler}>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
stroke-width="2"
class="w-3 h-3"
>
<path
fill-rule="evenodd"
d="M12.416 3.376a.75.75 0 0 1 .208 1.04l-5 7.5a.75.75 0 0 1-1.154.114l-3-3a.75.75 0 0 1 1.06-1.06l2.353 2.353 4.493-6.74a.75.75 0 0 1 1.04-.207Z"
clip-rule="evenodd"
/>
</svg>
</button>
</div> </div>
{/if} {/if}
<button <button
class=" cursor-pointer self-center p-0.5 space-x-1 flex h-fit items-center dark:hover:bg-gray-700 rounded-full transition border dark:border-gray-600 border-dashed" class=" cursor-pointer self-center p-0.5 flex h-fit items-center dark:hover:bg-gray-700 rounded-full transition border dark:border-gray-600 border-dashed"
type="button" type="button"
on:click={() => { on:click={() => {
showTagInput = !showTagInput; showTagInput = !showTagInput;
@ -80,6 +82,6 @@
</button> </button>
{#if label && !showTagInput} {#if label && !showTagInput}
<span class="text-xs pl-1.5 self-center">{label}</span> <span class="text-xs pl-2 self-center">{label}</span>
{/if} {/if}
</div> </div>

View File

@ -7,22 +7,23 @@
{#each tags as tag} {#each tags as tag}
<div <div
class="px-2 py-0.5 space-x-1 flex h-fit items-center rounded-full transition border dark:border-gray-800 dark:text-white" class="px-2 py-[0.5px] gap-0.5 flex justify-between h-fit items-center rounded-full transition border dark:border-gray-800 dark:text-white"
> >
<div class=" text-[0.7rem] font-medium self-center line-clamp-1"> <div class=" text-[0.7rem] font-medium self-center line-clamp-1">
{tag.name} {tag.name}
</div> </div>
<button <button
class=" m-auto self-center cursor-pointer" class="h-full flex self-center cursor-pointer"
on:click={() => { on:click={() => {
dispatch('delete', tag.name); dispatch('delete', tag.name);
}} }}
type="button"
> >
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16" viewBox="0 0 16 16"
fill="currentColor" fill="currentColor"
class="w-3 h-3" class="size-3 m-auto self-center translate-y-[0.3px] translate-x-[3px]"
> >
<path <path
d="M5.28 4.22a.75.75 0 0 0-1.06 1.06L6.94 8l-2.72 2.72a.75.75 0 1 0 1.06 1.06L8 9.06l2.72 2.72a.75.75 0 1 0 1.06-1.06L9.06 8l2.72-2.72a.75.75 0 0 0-1.06-1.06L8 6.94 5.28 4.22Z" d="M5.28 4.22a.75.75 0 0 0-1.06 1.06L6.94 8l-2.72 2.72a.75.75 0 1 0 1.06 1.06L8 9.06l2.72 2.72a.75.75 0 1 0 1.06-1.06L9.06 8l2.72-2.72a.75.75 0 0 0-1.06-1.06L8 6.94 5.28 4.22Z"

View File

@ -10,6 +10,7 @@
import AdvancedParams from '$lib/components/chat/Settings/Advanced/AdvancedParams.svelte'; import AdvancedParams from '$lib/components/chat/Settings/Advanced/AdvancedParams.svelte';
import Checkbox from '$lib/components/common/Checkbox.svelte'; import Checkbox from '$lib/components/common/Checkbox.svelte';
import Tags from '$lib/components/common/Tags.svelte';
const i18n = getContext('i18n'); const i18n = getContext('i18n');
@ -262,7 +263,7 @@
<button <button
class=" {info.meta.profile_image_url class=" {info.meta.profile_image_url
? '' ? ''
: 'p-6'} rounded-full dark:bg-gray-700 border border-dashed border-gray-200" : 'p-4'} rounded-full dark:bg-gray-700 border border-dashed border-gray-200 flex items-center"
type="button" type="button"
on:click={() => { on:click={() => {
filesInputElement.click(); filesInputElement.click();
@ -272,7 +273,7 @@
<img <img
src={info.meta.profile_image_url} src={info.meta.profile_image_url}
alt="modelfile profile" alt="modelfile profile"
class=" rounded-full w-20 h-20 object-cover" class=" rounded-full size-16 object-cover"
/> />
{:else} {:else}
<svg <svg
@ -338,17 +339,39 @@
</div> </div>
</div> </div>
<div class="my-2"> <div class="my-1">
<div class=" text-sm font-semibold mb-2">{$i18n.t('Description')}</div> <div class="flex w-full justify-between items-center mb-1">
<div class=" self-center text-sm font-semibold">{$i18n.t('Description')}</div>
<div> <button
class="p-1 text-xs flex rounded transition"
type="button"
on:click={() => {
if (info.meta.description === null) {
info.meta.description = '';
} else {
info.meta.description = null;
}
}}
>
{#if info.meta.description === null}
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{:else}
<span class="ml-2 self-center">{$i18n.t('Custom')}</span>
{/if}
</button>
</div>
{#if info.meta.description !== null}
<input <input
class="px-3 py-1.5 text-sm w-full bg-transparent border dark:border-gray-600 outline-none rounded-lg" class="px-3 py-1.5 text-sm w-full bg-transparent border dark:border-gray-600 outline-none rounded-lg"
placeholder={$i18n.t('Add a short description about what this model does')} placeholder={$i18n.t('Add a short description about what this model does')}
bind:value={info.meta.description} bind:value={info.meta.description}
/> />
{/if}
</div> </div>
</div>
<hr class=" dark:border-gray-850 my-1" />
<div class="my-2"> <div class="my-2">
<div class="flex w-full justify-between"> <div class="flex w-full justify-between">
@ -401,7 +424,9 @@
</div> </div>
</div> </div>
<div class="my-2"> <hr class=" dark:border-gray-850 my-1" />
<div class="my-1">
<div class="flex w-full justify-between items-center"> <div class="flex w-full justify-between items-center">
<div class="flex w-full justify-between items-center"> <div class="flex w-full justify-between items-center">
<div class=" self-center text-sm font-semibold">{$i18n.t('Prompt suggestions')}</div> <div class=" self-center text-sm font-semibold">{$i18n.t('Prompt suggestions')}</div>
@ -491,8 +516,8 @@
{/if} {/if}
</div> </div>
<div class="my-2"> <div class="my-1">
<div class="flex w-full justify-between"> <div class="flex w-full justify-between mb-1">
<div class=" self-center text-sm font-semibold">{$i18n.t('Capabilities')}</div> <div class=" self-center text-sm font-semibold">{$i18n.t('Capabilities')}</div>
</div> </div>
<div class="flex flex-col"> <div class="flex flex-col">
@ -505,7 +530,7 @@
}} }}
/> />
<div class=" py-1.5 text-sm w-full capitalize"> <div class=" py-0.5 text-sm w-full capitalize">
{$i18n.t(capability)} {$i18n.t(capability)}
</div> </div>
</div> </div>
@ -513,7 +538,30 @@
</div> </div>
</div> </div>
<div class="my-2 text-gray-500"> <div class="my-1">
<div class="flex w-full justify-between items-center">
<div class=" self-center text-sm font-semibold">{$i18n.t('Tags')}</div>
</div>
<div class="mt-2">
<Tags
tags={info?.meta?.tags ?? []}
deleteTag={(tagName) => {
info.meta.tags = info.meta.tags.filter((tag) => tag.name !== tagName);
}}
addTag={(tagName) => {
console.log(tagName);
if (!(info?.meta?.tags ?? null)) {
info.meta.tags = [{ name: tagName }];
} else {
info.meta.tags = [...info.meta.tags, { name: tagName }];
}
}}
/>
</div>
</div>
<div class="my-2 text-gray-300 dark:text-gray-700">
<div class="flex w-full justify-between mb-2"> <div class="flex w-full justify-between mb-2">
<div class=" self-center text-sm font-semibold">{$i18n.t('JSON Preview')}</div> <div class=" self-center text-sm font-semibold">{$i18n.t('JSON Preview')}</div>

View File

@ -13,6 +13,7 @@
import AdvancedParams from '$lib/components/chat/Settings/Advanced/AdvancedParams.svelte'; import AdvancedParams from '$lib/components/chat/Settings/Advanced/AdvancedParams.svelte';
import { getModels } from '$lib/apis'; import { getModels } from '$lib/apis';
import Checkbox from '$lib/components/common/Checkbox.svelte'; import Checkbox from '$lib/components/common/Checkbox.svelte';
import Tags from '$lib/components/common/Tags.svelte';
const i18n = getContext('i18n'); const i18n = getContext('i18n');
@ -44,7 +45,8 @@
meta: { meta: {
profile_image_url: '/favicon.png', profile_image_url: '/favicon.png',
description: '', description: '',
suggestion_prompts: null suggestion_prompts: null,
tags: []
}, },
params: { params: {
system: '' system: ''
@ -223,26 +225,26 @@
<div class="flex justify-center my-4"> <div class="flex justify-center my-4">
<div class="self-center"> <div class="self-center">
<button <button
class=" {info?.meta?.profile_image_url class=" {info.meta.profile_image_url
? '' ? ''
: 'p-6'} rounded-full dark:bg-gray-700 border border-dashed border-gray-200" : 'p-4'} rounded-full dark:bg-gray-700 border border-dashed border-gray-200 flex items-center"
type="button" type="button"
on:click={() => { on:click={() => {
filesInputElement.click(); filesInputElement.click();
}} }}
> >
{#if info?.meta?.profile_image_url} {#if info.meta.profile_image_url}
<img <img
src={info?.meta?.profile_image_url} src={info.meta.profile_image_url}
alt="modelfile profile" alt="modelfile profile"
class=" rounded-full w-20 h-20 object-cover" class=" rounded-full size-16 object-cover"
/> />
{:else} {:else}
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24" viewBox="0 0 24 24"
fill="currentColor" fill="currentColor"
class="w-8" class="size-8"
> >
<path <path
fill-rule="evenodd" fill-rule="evenodd"
@ -255,9 +257,9 @@
</div> </div>
</div> </div>
<div class="my-2 flex space-x-2"> <div class="mt-2 my-1 flex space-x-2">
<div class="flex-1"> <div class="flex-1">
<div class=" text-sm font-semibold mb-2">{$i18n.t('Name')}*</div> <div class=" text-sm font-semibold mb-1">{$i18n.t('Name')}*</div>
<div> <div>
<input <input
@ -270,7 +272,7 @@
</div> </div>
<div class="flex-1"> <div class="flex-1">
<div class=" text-sm font-semibold mb-2">{$i18n.t('Model ID')}*</div> <div class=" text-sm font-semibold mb-1">{$i18n.t('Model ID')}*</div>
<div> <div>
<input <input
@ -285,8 +287,8 @@
</div> </div>
{#if model.preset} {#if model.preset}
<div class="my-2"> <div class="my-1">
<div class=" text-sm font-semibold mb-2">{$i18n.t('Base Model (From)')}</div> <div class=" text-sm font-semibold mb-1">{$i18n.t('Base Model (From)')}</div>
<div> <div>
<select <select
@ -304,17 +306,39 @@
</div> </div>
{/if} {/if}
<div class="my-2"> <div class="my-1">
<div class=" text-sm font-semibold mb-2">{$i18n.t('Description')}</div> <div class="flex w-full justify-between items-center">
<div class=" self-center text-sm font-semibold">{$i18n.t('Description')}</div>
<div> <button
class="p-1 text-xs flex rounded transition"
type="button"
on:click={() => {
if (info.meta.description === null) {
info.meta.description = '';
} else {
info.meta.description = null;
}
}}
>
{#if info.meta.description === null}
<span class="ml-2 self-center">{$i18n.t('Default')}</span>
{:else}
<span class="ml-2 self-center">{$i18n.t('Custom')}</span>
{/if}
</button>
</div>
{#if info.meta.description !== null}
<input <input
class="px-3 py-1.5 text-sm w-full bg-transparent border dark:border-gray-600 outline-none rounded-lg" class="mt-1 px-3 py-1.5 text-sm w-full bg-transparent border dark:border-gray-600 outline-none rounded-lg"
placeholder={$i18n.t('Add a short description about what this model does')} placeholder={$i18n.t('Add a short description about what this model does')}
bind:value={info.meta.description} bind:value={info.meta.description}
/> />
{/if}
</div> </div>
</div>
<hr class=" dark:border-gray-850 my-1" />
<div class="my-2"> <div class="my-2">
<div class="flex w-full justify-between"> <div class="flex w-full justify-between">
@ -369,7 +393,9 @@
</div> </div>
</div> </div>
<div class="my-2"> <hr class=" dark:border-gray-850 my-1" />
<div class="my-1">
<div class="flex w-full justify-between items-center"> <div class="flex w-full justify-between items-center">
<div class="flex w-full justify-between items-center"> <div class="flex w-full justify-between items-center">
<div class=" self-center text-sm font-semibold">{$i18n.t('Prompt suggestions')}</div> <div class=" self-center text-sm font-semibold">{$i18n.t('Prompt suggestions')}</div>
@ -459,7 +485,7 @@
{/if} {/if}
</div> </div>
<div class="my-2"> <div class="my-1">
<div class="flex w-full justify-between mb-1"> <div class="flex w-full justify-between mb-1">
<div class=" self-center text-sm font-semibold">{$i18n.t('Capabilities')}</div> <div class=" self-center text-sm font-semibold">{$i18n.t('Capabilities')}</div>
</div> </div>
@ -481,7 +507,30 @@
</div> </div>
</div> </div>
<div class="my-2 text-gray-500"> <div class="my-1">
<div class="flex w-full justify-between items-center">
<div class=" self-center text-sm font-semibold">{$i18n.t('Tags')}</div>
</div>
<div class="mt-2">
<Tags
tags={info?.meta?.tags ?? []}
deleteTag={(tagName) => {
info.meta.tags = info.meta.tags.filter((tag) => tag.name !== tagName);
}}
addTag={(tagName) => {
console.log(tagName);
if (!(info?.meta?.tags ?? null)) {
info.meta.tags = [{ name: tagName }];
} else {
info.meta.tags = [...info.meta.tags, { name: tagName }];
}
}}
/>
</div>
</div>
<div class="my-2 text-gray-300 dark:text-gray-700">
<div class="flex w-full justify-between mb-2"> <div class="flex w-full justify-between mb-2">
<div class=" self-center text-sm font-semibold">{$i18n.t('JSON Preview')}</div> <div class=" self-center text-sm font-semibold">{$i18n.t('JSON Preview')}</div>