refac
This commit is contained in:
@@ -71,6 +71,8 @@
|
||||
let models = null;
|
||||
let modelsConfig = null;
|
||||
let modelOrderList: string[] = [];
|
||||
let defaultModelIds: string[] = [];
|
||||
let defaultPinnedModelIds: string[] = [];
|
||||
|
||||
let workspaceModels: ModelListItem[] = [];
|
||||
let baseModels: ModelListItem[] = [];
|
||||
@@ -121,6 +123,9 @@
|
||||
return 'text-gray-500 dark:text-gray-400';
|
||||
};
|
||||
|
||||
const isDefaultModel = (model) => defaultModelIds.includes(model.id);
|
||||
const isDefaultPinnedModel = (model) => defaultPinnedModelIds.includes(model.id);
|
||||
|
||||
$: if (models) {
|
||||
const modelOrder = new Map(modelOrderList.map((id, idx) => [id, idx]));
|
||||
|
||||
@@ -230,6 +235,10 @@
|
||||
|
||||
modelsConfig = await getModelsConfig(localStorage.token);
|
||||
modelOrderList = modelsConfig?.MODEL_ORDER_LIST ?? [];
|
||||
defaultModelIds = (modelsConfig?.DEFAULT_MODELS ?? '').split(',').filter((id) => id);
|
||||
defaultPinnedModelIds = (modelsConfig?.DEFAULT_PINNED_MODELS ?? '')
|
||||
.split(',')
|
||||
.filter((id) => id);
|
||||
|
||||
tags = await getBaseModelTags(localStorage.token);
|
||||
if (selectedTag && !tags.includes(selectedTag)) {
|
||||
@@ -282,8 +291,8 @@
|
||||
savingModelOrder = true;
|
||||
|
||||
const res = await setModelsConfig(localStorage.token, {
|
||||
DEFAULT_MODELS: modelsConfig?.DEFAULT_MODELS ?? null,
|
||||
DEFAULT_PINNED_MODELS: modelsConfig?.DEFAULT_PINNED_MODELS ?? null,
|
||||
DEFAULT_MODELS: defaultModelIds.join(','),
|
||||
DEFAULT_PINNED_MODELS: defaultPinnedModelIds.join(','),
|
||||
MODEL_ORDER_LIST: orderedModelIds,
|
||||
DEFAULT_MODEL_METADATA: modelsConfig?.DEFAULT_MODEL_METADATA ?? null,
|
||||
DEFAULT_MODEL_PARAMS: modelsConfig?.DEFAULT_MODEL_PARAMS ?? null
|
||||
@@ -307,6 +316,65 @@
|
||||
savingModelOrder = false;
|
||||
};
|
||||
|
||||
const saveModelDefaults = async (
|
||||
nextDefaultModelIds: string[],
|
||||
nextDefaultPinnedModelIds: string[],
|
||||
successMessage: string
|
||||
) => {
|
||||
const previousDefaultModelIds = defaultModelIds;
|
||||
const previousDefaultPinnedModelIds = defaultPinnedModelIds;
|
||||
|
||||
defaultModelIds = nextDefaultModelIds;
|
||||
defaultPinnedModelIds = nextDefaultPinnedModelIds;
|
||||
|
||||
const res = await setModelsConfig(localStorage.token, {
|
||||
DEFAULT_MODELS: nextDefaultModelIds.join(','),
|
||||
DEFAULT_PINNED_MODELS: nextDefaultPinnedModelIds.join(','),
|
||||
MODEL_ORDER_LIST: modelsConfig?.MODEL_ORDER_LIST ?? [],
|
||||
DEFAULT_MODEL_METADATA: modelsConfig?.DEFAULT_MODEL_METADATA ?? null,
|
||||
DEFAULT_MODEL_PARAMS: modelsConfig?.DEFAULT_MODEL_PARAMS ?? null
|
||||
}).catch((error) => {
|
||||
toast.error(`${error}`);
|
||||
return null;
|
||||
});
|
||||
|
||||
if (res) {
|
||||
modelsConfig = res;
|
||||
toast.success(successMessage);
|
||||
} else {
|
||||
defaultModelIds = previousDefaultModelIds;
|
||||
defaultPinnedModelIds = previousDefaultPinnedModelIds;
|
||||
}
|
||||
};
|
||||
|
||||
const toggleDefaultModelHandler = async (model) => {
|
||||
const nextDefaultModelIds = isDefaultModel(model)
|
||||
? defaultModelIds.filter((id) => id !== model.id)
|
||||
: [...new Set([...defaultModelIds, model.id])];
|
||||
|
||||
await saveModelDefaults(
|
||||
nextDefaultModelIds,
|
||||
defaultPinnedModelIds,
|
||||
isDefaultModel(model)
|
||||
? $i18n.t('Model removed from selected models')
|
||||
: $i18n.t('Model added to selected models')
|
||||
);
|
||||
};
|
||||
|
||||
const toggleDefaultPinnedModelHandler = async (model) => {
|
||||
const nextDefaultPinnedModelIds = isDefaultPinnedModel(model)
|
||||
? defaultPinnedModelIds.filter((id) => id !== model.id)
|
||||
: [...new Set([...defaultPinnedModelIds, model.id])];
|
||||
|
||||
await saveModelDefaults(
|
||||
defaultModelIds,
|
||||
nextDefaultPinnedModelIds,
|
||||
isDefaultPinnedModel(model)
|
||||
? $i18n.t('Model removed from pinned models')
|
||||
: $i18n.t('Model added to pinned models')
|
||||
);
|
||||
};
|
||||
|
||||
const positionChangeHandler = async (event) => {
|
||||
const { oldIndex, newIndex, item } = event;
|
||||
|
||||
@@ -803,7 +871,7 @@
|
||||
class="flex cursor-pointer transition w-full px-2 py-1 rounded-xl hover:bg-gray-50/70 dark:hover:bg-gray-850/50 {model
|
||||
?.meta?.hidden
|
||||
? 'opacity-50 dark:opacity-50'
|
||||
: ''}"
|
||||
: ''}"
|
||||
id="model-item-{model.id}"
|
||||
>
|
||||
<div class="self-center pr-1 text-gray-400 dark:text-gray-600">
|
||||
@@ -876,6 +944,22 @@
|
||||
>
|
||||
{modelAccessLabel(model)}
|
||||
</span>
|
||||
|
||||
{#if isDefaultModel(model)}
|
||||
<span
|
||||
class="shrink-0 text-[11px] font-normal leading-4 text-gray-500 dark:text-gray-400"
|
||||
>
|
||||
{$i18n.t('Selected')}
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
{#if isDefaultPinnedModel(model)}
|
||||
<span
|
||||
class="shrink-0 text-[11px] font-normal leading-4 text-gray-500 dark:text-gray-400"
|
||||
>
|
||||
{$i18n.t('Pinned')}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
@@ -934,6 +1018,14 @@
|
||||
privacyHandler={() => {
|
||||
toggleModelPrivacyHandler(model);
|
||||
}}
|
||||
isDefaultSelected={isDefaultModel(model)}
|
||||
isDefaultPinned={isDefaultPinnedModel(model)}
|
||||
defaultSelectedHandler={() => {
|
||||
toggleDefaultModelHandler(model);
|
||||
}}
|
||||
defaultPinnedHandler={() => {
|
||||
toggleDefaultPinnedModelHandler(model);
|
||||
}}
|
||||
pinModelHandler={() => {
|
||||
pinModelHandler(model.id);
|
||||
}}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
import ArrowUpCircle from '$lib/components/icons/ArrowUpCircle.svelte';
|
||||
import Pin from '$lib/components/icons/Pin.svelte';
|
||||
import PinSlash from '$lib/components/icons/PinSlash.svelte';
|
||||
import Check from '$lib/components/icons/Check.svelte';
|
||||
import GlobeAlt from '$lib/components/icons/GlobeAlt.svelte';
|
||||
import LockClosed from '$lib/components/icons/LockClosed.svelte';
|
||||
|
||||
@@ -28,6 +29,10 @@
|
||||
export let exportHandler: Function;
|
||||
export let hideHandler: Function;
|
||||
export let privacyHandler: Function;
|
||||
export let isDefaultSelected = false;
|
||||
export let isDefaultPinned = false;
|
||||
export let defaultSelectedHandler: Function;
|
||||
export let defaultPinnedHandler: Function;
|
||||
export let pinModelHandler: Function;
|
||||
export let copyLinkHandler: Function;
|
||||
export let cloneHandler: Function;
|
||||
@@ -108,6 +113,46 @@
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="select-none flex w-full gap-2 items-center h-[1.6875rem] px-2 text-[13px] font-normal cursor-pointer hover:bg-gray-50/40 dark:hover:bg-gray-800/40 rounded-xl"
|
||||
on:click={async () => {
|
||||
show = false;
|
||||
await defaultSelectedHandler();
|
||||
}}
|
||||
>
|
||||
<Check className="size-3.5" />
|
||||
|
||||
<div class="flex items-center">
|
||||
{#if isDefaultSelected}
|
||||
{$i18n.t('Remove Selected Model')}
|
||||
{:else}
|
||||
{$i18n.t('Set as Selected Model')}
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="select-none flex w-full gap-2 items-center h-[1.6875rem] px-2 text-[13px] font-normal cursor-pointer hover:bg-gray-50/40 dark:hover:bg-gray-800/40 rounded-xl"
|
||||
on:click={async () => {
|
||||
show = false;
|
||||
await defaultPinnedHandler();
|
||||
}}
|
||||
>
|
||||
{#if isDefaultPinned}
|
||||
<PinSlash className="size-3.5" />
|
||||
{:else}
|
||||
<Pin className="size-3.5" />
|
||||
{/if}
|
||||
|
||||
<div class="flex items-center">
|
||||
{#if isDefaultPinned}
|
||||
{$i18n.t('Remove Pinned Model')}
|
||||
{:else}
|
||||
{$i18n.t('Set as Pinned Model')}
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="select-none flex w-full gap-2 items-center h-[1.6875rem] px-2 text-[13px] font-normal cursor-pointer hover:bg-gray-50/40 dark:hover:bg-gray-800/40 rounded-xl"
|
||||
on:click={() => {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import { getContext, onMount } from 'svelte';
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
import { models, config as _config } from '$lib/stores';
|
||||
import { config as _config } from '$lib/stores';
|
||||
import { DEFAULT_CAPABILITIES } from '$lib/constants';
|
||||
import { getModelsConfig, setModelsConfig, setDefaultPromptSuggestions } from '$lib/apis/configs';
|
||||
import { getBackendConfig } from '$lib/apis';
|
||||
@@ -14,7 +14,6 @@
|
||||
import ChevronUp from '$lib/components/icons/ChevronUp.svelte';
|
||||
import ChevronDown from '$lib/components/icons/ChevronDown.svelte';
|
||||
import XMark from '$lib/components/icons/XMark.svelte';
|
||||
import ModelSelector from './ModelSelector.svelte';
|
||||
import AdvancedParams from '$lib/components/chat/Settings/Advanced/AdvancedParams.svelte';
|
||||
|
||||
import Capabilities from '$lib/components/workspace/Models/Capabilities.svelte';
|
||||
@@ -29,10 +28,6 @@
|
||||
|
||||
let config = null;
|
||||
|
||||
let defaultModelIds = [];
|
||||
|
||||
let defaultPinnedModelIds = [];
|
||||
|
||||
let modelIds = [];
|
||||
|
||||
let loading = false;
|
||||
@@ -52,30 +47,7 @@
|
||||
const init = async () => {
|
||||
config = await getModelsConfig(localStorage.token);
|
||||
|
||||
if (config?.DEFAULT_MODELS) {
|
||||
defaultModelIds = (config?.DEFAULT_MODELS).split(',').filter((id) => id);
|
||||
} else {
|
||||
defaultModelIds = [];
|
||||
}
|
||||
|
||||
if (config?.DEFAULT_PINNED_MODELS) {
|
||||
defaultPinnedModelIds = (config?.DEFAULT_PINNED_MODELS).split(',').filter((id) => id);
|
||||
} else {
|
||||
defaultPinnedModelIds = [];
|
||||
}
|
||||
|
||||
const modelOrderList = config.MODEL_ORDER_LIST || [];
|
||||
const allModelIds = $models.map((model) => model.id);
|
||||
|
||||
// Create a Set for quick lookup of ordered IDs
|
||||
const orderedSet = new Set(modelOrderList);
|
||||
|
||||
modelIds = [
|
||||
// Add all IDs from MODEL_ORDER_LIST that exist in allModelIds
|
||||
...modelOrderList.filter((id) => orderedSet.has(id) && allModelIds.includes(id)),
|
||||
// Add remaining IDs not in MODEL_ORDER_LIST, sorted alphabetically
|
||||
...allModelIds.filter((id) => !orderedSet.has(id)).sort((a, b) => a.localeCompare(b))
|
||||
];
|
||||
modelIds = config.MODEL_ORDER_LIST || [];
|
||||
|
||||
const savedMeta = config?.DEFAULT_MODEL_METADATA;
|
||||
if (savedMeta && Object.keys(savedMeta).length > 0) {
|
||||
@@ -101,8 +73,8 @@
|
||||
};
|
||||
|
||||
const res = await setModelsConfig(localStorage.token, {
|
||||
DEFAULT_MODELS: defaultModelIds.join(','),
|
||||
DEFAULT_PINNED_MODELS: defaultPinnedModelIds.join(','),
|
||||
DEFAULT_MODELS: config?.DEFAULT_MODELS ?? null,
|
||||
DEFAULT_PINNED_MODELS: config?.DEFAULT_PINNED_MODELS ?? null,
|
||||
MODEL_ORDER_LIST: modelIds,
|
||||
DEFAULT_MODEL_METADATA: metadata,
|
||||
DEFAULT_MODEL_PARAMS: Object.fromEntries(
|
||||
@@ -173,147 +145,123 @@
|
||||
|
||||
<div class="flex-1 mt-1 lg:mt-1 lg:h-[30rem] lg:max-h-[30rem] flex flex-col min-w-0">
|
||||
<div class="w-full h-full overflow-y-auto overflow-x-hidden scrollbar-hidden">
|
||||
<ModelSelector
|
||||
title={$i18n.t('Selected Models')}
|
||||
tooltip={$i18n.t(
|
||||
'Set the default models that are automatically selected for all users when a new chat is created.'
|
||||
)}
|
||||
models={$models.filter((model) => !(model?.info?.meta?.hidden ?? false))}
|
||||
bind:modelIds={defaultModelIds}
|
||||
/>
|
||||
<div>
|
||||
<button
|
||||
class="flex w-full justify-between items-center"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
showDefaultPromptSuggestions = !showDefaultPromptSuggestions;
|
||||
}}
|
||||
>
|
||||
<div class="text-xs text-gray-500 font-normal">
|
||||
{$i18n.t('Prompt Suggestions')}
|
||||
</div>
|
||||
<div>
|
||||
{#if showDefaultPromptSuggestions}
|
||||
<ChevronUp className="size-3" />
|
||||
{:else}
|
||||
<ChevronDown className="size-3" />
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<hr class=" border-gray-50 dark:border-gray-800/10 my-2.5 w-full" />
|
||||
{#if showDefaultPromptSuggestions}
|
||||
<div class="mt-2">
|
||||
<PromptSuggestions bind:promptSuggestions />
|
||||
|
||||
<ModelSelector
|
||||
title={$i18n.t('Pinned Models')}
|
||||
tooltip={$i18n.t(
|
||||
'Set the models that are automatically pinned to the sidebar for all users.'
|
||||
)}
|
||||
models={$models.filter((model) => !(model?.info?.meta?.hidden ?? false))}
|
||||
bind:modelIds={defaultPinnedModelIds}
|
||||
/>
|
||||
{#if promptSuggestions.length > 0}
|
||||
<div class="text-xs text-left w-full mt-2 text-gray-500">
|
||||
{$i18n.t(
|
||||
'Adjusting these settings will apply changes universally to all users.'
|
||||
)}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<hr class=" border-gray-50 dark:border-gray-800/10 my-2.5 w-full" />
|
||||
<hr class=" border-gray-50 dark:border-gray-800/10 my-2.5 w-full" />
|
||||
|
||||
<div>
|
||||
<button
|
||||
class="flex w-full justify-between items-center"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
showDefaultPromptSuggestions = !showDefaultPromptSuggestions;
|
||||
}}
|
||||
>
|
||||
<div class="text-xs text-gray-500 font-normal">
|
||||
{$i18n.t('Prompt Suggestions')}
|
||||
</div>
|
||||
<div>
|
||||
{#if showDefaultPromptSuggestions}
|
||||
<ChevronUp className="size-3" />
|
||||
{:else}
|
||||
<ChevronDown className="size-3" />
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
<div>
|
||||
<button
|
||||
class="flex w-full justify-between items-center"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
showDefaultCapabilities = !showDefaultCapabilities;
|
||||
}}
|
||||
>
|
||||
<div class="text-xs text-gray-500 font-normal">
|
||||
{$i18n.t('Model Capabilities')}
|
||||
</div>
|
||||
<div>
|
||||
{#if showDefaultCapabilities}
|
||||
<ChevronUp className="size-3" />
|
||||
{:else}
|
||||
<ChevronDown className="size-3" />
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
|
||||
{#if showDefaultPromptSuggestions}
|
||||
<div class="mt-2">
|
||||
<PromptSuggestions bind:promptSuggestions />
|
||||
{#if showDefaultCapabilities}
|
||||
<div class="mt-2">
|
||||
<Capabilities bind:capabilities={defaultCapabilities} />
|
||||
|
||||
{#if promptSuggestions.length > 0}
|
||||
<div class="text-xs text-left w-full mt-2 text-gray-500">
|
||||
{$i18n.t(
|
||||
'Adjusting these settings will apply changes universally to all users.'
|
||||
)}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if Object.keys(defaultCapabilities).filter((key) => defaultCapabilities[key]).length > 0}
|
||||
{@const availableFeatures = Object.entries(defaultCapabilities)
|
||||
.filter(
|
||||
([key, value]) =>
|
||||
value &&
|
||||
['web_search', 'code_interpreter', 'image_generation'].includes(key)
|
||||
)
|
||||
.map(([key, value]) => key)}
|
||||
|
||||
<hr class=" border-gray-50 dark:border-gray-800/10 my-2.5 w-full" />
|
||||
|
||||
<div>
|
||||
<button
|
||||
class="flex w-full justify-between items-center"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
showDefaultCapabilities = !showDefaultCapabilities;
|
||||
}}
|
||||
>
|
||||
<div class="text-xs text-gray-500 font-normal">
|
||||
{$i18n.t('Model Capabilities')}
|
||||
</div>
|
||||
<div>
|
||||
{#if showDefaultCapabilities}
|
||||
<ChevronUp className="size-3" />
|
||||
{:else}
|
||||
<ChevronDown className="size-3" />
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
|
||||
{#if showDefaultCapabilities}
|
||||
<div class="mt-2">
|
||||
<Capabilities bind:capabilities={defaultCapabilities} />
|
||||
|
||||
{#if Object.keys(defaultCapabilities).filter((key) => defaultCapabilities[key]).length > 0}
|
||||
{@const availableFeatures = Object.entries(defaultCapabilities)
|
||||
.filter(
|
||||
([key, value]) =>
|
||||
value &&
|
||||
['web_search', 'code_interpreter', 'image_generation'].includes(
|
||||
key
|
||||
)
|
||||
)
|
||||
.map(([key, value]) => key)}
|
||||
|
||||
{#if availableFeatures.length > 0}
|
||||
<div class="mt-4">
|
||||
<DefaultFeatures
|
||||
{availableFeatures}
|
||||
bind:featureIds={defaultFeatureIds}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
{#if defaultCapabilities.builtin_tools}
|
||||
{#if availableFeatures.length > 0}
|
||||
<div class="mt-4">
|
||||
<BuiltinTools bind:builtinTools />
|
||||
<DefaultFeatures
|
||||
{availableFeatures}
|
||||
bind:featureIds={defaultFeatureIds}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<hr class=" border-gray-50 dark:border-gray-800/10 my-2.5 w-full" />
|
||||
{#if defaultCapabilities.builtin_tools}
|
||||
<div class="mt-4">
|
||||
<BuiltinTools bind:builtinTools />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button
|
||||
class="flex w-full justify-between items-center"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
showDefaultParams = !showDefaultParams;
|
||||
}}
|
||||
>
|
||||
<div class="text-xs text-gray-500 font-normal">
|
||||
{$i18n.t('Model Parameters')}
|
||||
</div>
|
||||
<div>
|
||||
{#if showDefaultParams}
|
||||
<ChevronUp className="size-3" />
|
||||
{:else}
|
||||
<ChevronDown className="size-3" />
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
<hr class=" border-gray-50 dark:border-gray-800/10 my-2.5 w-full" />
|
||||
|
||||
{#if showDefaultParams}
|
||||
<div class="mt-2">
|
||||
<AdvancedParams admin={true} custom={true} bind:params={defaultParams} />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
class="flex w-full justify-between items-center"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
showDefaultParams = !showDefaultParams;
|
||||
}}
|
||||
>
|
||||
<div class="text-xs text-gray-500 font-normal">
|
||||
{$i18n.t('Model Parameters')}
|
||||
</div>
|
||||
<div>
|
||||
{#if showDefaultParams}
|
||||
<ChevronUp className="size-3" />
|
||||
{:else}
|
||||
<ChevronDown className="size-3" />
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
|
||||
{#if showDefaultParams}
|
||||
<div class="mt-2">
|
||||
<AdvancedParams admin={true} custom={true} bind:params={defaultParams} />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end items-center pt-3 text-sm font-normal gap-1.5">
|
||||
|
||||
Reference in New Issue
Block a user