mirror of
https://github.com/open-webui/open-webui
synced 2025-02-20 12:00:22 +00:00
feat: model tag support
This commit is contained in:
parent
0cf9b07ec2
commit
eca20b1b2c
@ -39,7 +39,7 @@
|
||||
{#if !dismissed}
|
||||
{#if mounted}
|
||||
<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 }}
|
||||
>
|
||||
<div class=" flex flex-col md:flex-row md:items-center flex-1 text-sm w-fit gap-1.5">
|
||||
|
@ -14,6 +14,7 @@
|
||||
onOpenChange={(state) => {
|
||||
dispatch('change', state);
|
||||
}}
|
||||
typeahead={false}
|
||||
>
|
||||
<DropdownMenu.Trigger>
|
||||
<slot />
|
||||
|
@ -11,7 +11,7 @@
|
||||
export let addTag: Function;
|
||||
</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
|
||||
{tags}
|
||||
on:delete={(e) => {
|
||||
|
@ -22,26 +22,12 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="flex space-x-1 pl-1.5">
|
||||
<div class="flex {showTagInput ? 'flex-row-reverse' : ''}">
|
||||
{#if showTagInput}
|
||||
<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
|
||||
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')}
|
||||
list="tagOptions"
|
||||
on:keydown={(event) => {
|
||||
@ -55,11 +41,27 @@
|
||||
<option value={tag.name} />
|
||||
{/each}
|
||||
</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>
|
||||
{/if}
|
||||
|
||||
<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"
|
||||
on:click={() => {
|
||||
showTagInput = !showTagInput;
|
||||
@ -80,6 +82,6 @@
|
||||
</button>
|
||||
|
||||
{#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}
|
||||
</div>
|
||||
|
@ -7,22 +7,23 @@
|
||||
|
||||
{#each tags as tag}
|
||||
<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">
|
||||
{tag.name}
|
||||
</div>
|
||||
<button
|
||||
class=" m-auto self-center cursor-pointer"
|
||||
class="h-full flex self-center cursor-pointer"
|
||||
on:click={() => {
|
||||
dispatch('delete', tag.name);
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 16 16"
|
||||
fill="currentColor"
|
||||
class="w-3 h-3"
|
||||
class="size-3 m-auto self-center translate-y-[0.3px] translate-x-[3px]"
|
||||
>
|
||||
<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"
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
import AdvancedParams from '$lib/components/chat/Settings/Advanced/AdvancedParams.svelte';
|
||||
import Checkbox from '$lib/components/common/Checkbox.svelte';
|
||||
import Tags from '$lib/components/common/Tags.svelte';
|
||||
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
@ -262,7 +263,7 @@
|
||||
<button
|
||||
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"
|
||||
on:click={() => {
|
||||
filesInputElement.click();
|
||||
@ -272,7 +273,7 @@
|
||||
<img
|
||||
src={info.meta.profile_image_url}
|
||||
alt="modelfile profile"
|
||||
class=" rounded-full w-20 h-20 object-cover"
|
||||
class=" rounded-full size-16 object-cover"
|
||||
/>
|
||||
{:else}
|
||||
<svg
|
||||
@ -338,18 +339,40 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="my-2">
|
||||
<div class=" text-sm font-semibold mb-2">{$i18n.t('Description')}</div>
|
||||
<div class="my-1">
|
||||
<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
|
||||
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')}
|
||||
bind:value={info.meta.description}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<hr class=" dark:border-gray-850 my-1" />
|
||||
|
||||
<div class="my-2">
|
||||
<div class="flex w-full justify-between">
|
||||
<div class=" self-center text-sm font-semibold">{$i18n.t('Model Params')}</div>
|
||||
@ -401,7 +424,9 @@
|
||||
</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=" self-center text-sm font-semibold">{$i18n.t('Prompt suggestions')}</div>
|
||||
@ -491,8 +516,8 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="my-2">
|
||||
<div class="flex w-full justify-between">
|
||||
<div class="my-1">
|
||||
<div class="flex w-full justify-between mb-1">
|
||||
<div class=" self-center text-sm font-semibold">{$i18n.t('Capabilities')}</div>
|
||||
</div>
|
||||
<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)}
|
||||
</div>
|
||||
</div>
|
||||
@ -513,7 +538,30 @@
|
||||
</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=" self-center text-sm font-semibold">{$i18n.t('JSON Preview')}</div>
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
import AdvancedParams from '$lib/components/chat/Settings/Advanced/AdvancedParams.svelte';
|
||||
import { getModels } from '$lib/apis';
|
||||
import Checkbox from '$lib/components/common/Checkbox.svelte';
|
||||
import Tags from '$lib/components/common/Tags.svelte';
|
||||
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
@ -44,7 +45,8 @@
|
||||
meta: {
|
||||
profile_image_url: '/favicon.png',
|
||||
description: '',
|
||||
suggestion_prompts: null
|
||||
suggestion_prompts: null,
|
||||
tags: []
|
||||
},
|
||||
params: {
|
||||
system: ''
|
||||
@ -223,26 +225,26 @@
|
||||
<div class="flex justify-center my-4">
|
||||
<div class="self-center">
|
||||
<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"
|
||||
on:click={() => {
|
||||
filesInputElement.click();
|
||||
}}
|
||||
>
|
||||
{#if info?.meta?.profile_image_url}
|
||||
{#if info.meta.profile_image_url}
|
||||
<img
|
||||
src={info?.meta?.profile_image_url}
|
||||
src={info.meta.profile_image_url}
|
||||
alt="modelfile profile"
|
||||
class=" rounded-full w-20 h-20 object-cover"
|
||||
class=" rounded-full size-16 object-cover"
|
||||
/>
|
||||
{:else}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
class="w-8"
|
||||
class="size-8"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
@ -255,9 +257,9 @@
|
||||
</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=" text-sm font-semibold mb-2">{$i18n.t('Name')}*</div>
|
||||
<div class=" text-sm font-semibold mb-1">{$i18n.t('Name')}*</div>
|
||||
|
||||
<div>
|
||||
<input
|
||||
@ -270,7 +272,7 @@
|
||||
</div>
|
||||
|
||||
<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>
|
||||
<input
|
||||
@ -285,8 +287,8 @@
|
||||
</div>
|
||||
|
||||
{#if model.preset}
|
||||
<div class="my-2">
|
||||
<div class=" text-sm font-semibold mb-2">{$i18n.t('Base Model (From)')}</div>
|
||||
<div class="my-1">
|
||||
<div class=" text-sm font-semibold mb-1">{$i18n.t('Base Model (From)')}</div>
|
||||
|
||||
<div>
|
||||
<select
|
||||
@ -304,18 +306,40 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="my-2">
|
||||
<div class=" text-sm font-semibold mb-2">{$i18n.t('Description')}</div>
|
||||
<div class="my-1">
|
||||
<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
|
||||
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')}
|
||||
bind:value={info.meta.description}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<hr class=" dark:border-gray-850 my-1" />
|
||||
|
||||
<div class="my-2">
|
||||
<div class="flex w-full justify-between">
|
||||
<div class=" self-center text-sm font-semibold">{$i18n.t('Model Params')}</div>
|
||||
@ -369,7 +393,9 @@
|
||||
</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=" self-center text-sm font-semibold">{$i18n.t('Prompt suggestions')}</div>
|
||||
@ -459,7 +485,7 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="my-2">
|
||||
<div class="my-1">
|
||||
<div class="flex w-full justify-between mb-1">
|
||||
<div class=" self-center text-sm font-semibold">{$i18n.t('Capabilities')}</div>
|
||||
</div>
|
||||
@ -481,7 +507,30 @@
|
||||
</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=" self-center text-sm font-semibold">{$i18n.t('JSON Preview')}</div>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user