mirror of
https://github.com/ggml-org/llama.cpp.git
synced 2026-09-29 01:17:36 -05:00
ui : drop the providers settings section and the model grouping setting
Assisted-by: pi:llama.cpp/GLM-5.3-Flash
This commit is contained in:
@@ -14,14 +14,7 @@
|
||||
saveOverrides
|
||||
} from './utils';
|
||||
import { LOCAL_BACKEND_ID } from '$lib/constants';
|
||||
import { ModelGroupingMode } from '$lib/enums/settings.enums';
|
||||
import {
|
||||
backendsStore,
|
||||
conversationsStore,
|
||||
modelsStore,
|
||||
settingsStore,
|
||||
uiStore
|
||||
} from '$lib/stores';
|
||||
import { backendsStore, conversationsStore, modelsStore, uiStore } from '$lib/stores';
|
||||
import type { ModelOption } from '$lib/types/models';
|
||||
import { getBackend } from '$lib/utils/api-base';
|
||||
import { getBackendCapabilities } from '$lib/utils/backend';
|
||||
@@ -142,79 +135,34 @@
|
||||
});
|
||||
}
|
||||
|
||||
// by capability: one block whose models can load and unload, one that is chat only
|
||||
if (settingsStore.config.modelGrouping === ModelGroupingMode.COMPAT) {
|
||||
const local = (entry: ModelQuantGroup) => entry.base.backendId === LOCAL_BACKEND_ID;
|
||||
const loadable: ModelQuantGroup[] = [];
|
||||
const chatOnly: ModelQuantGroup[] = [];
|
||||
const localItems = byBackend.get(LOCAL_BACKEND_ID);
|
||||
|
||||
for (const entry of entries) {
|
||||
if (claimed.has(entry.key) || hiddenKeys.has(entry.key)) continue;
|
||||
if (localItems?.length) {
|
||||
ordered.push({
|
||||
backendId: LOCAL_BACKEND_ID,
|
||||
isLocal: true,
|
||||
items: localItems,
|
||||
key: LOCAL_BACKEND_ID,
|
||||
kind: 'local',
|
||||
label: 'Local models'
|
||||
});
|
||||
}
|
||||
|
||||
const canLoad = getBackendCapabilities(getBackend(entry.base.backendId)).loadUnload;
|
||||
for (const backend of backendsStore.enabled) {
|
||||
if (backend.id === LOCAL_BACKEND_ID) continue;
|
||||
|
||||
(canLoad ? loadable : chatOnly).push(entry);
|
||||
}
|
||||
const items = byBackend.get(backend.id);
|
||||
|
||||
// the bundled server leads the block it belongs to
|
||||
const leading = (list: ModelQuantGroup[]) =>
|
||||
[...list].sort((a, b) => Number(local(b)) - Number(local(a)));
|
||||
|
||||
if (loadable.length) {
|
||||
if (items?.length) {
|
||||
ordered.push({
|
||||
backendId: null,
|
||||
backendId: backend.id,
|
||||
isLocal: false,
|
||||
items: leading(loadable),
|
||||
key: 'llama-compat',
|
||||
kind: 'compat',
|
||||
label: 'Llama-compat'
|
||||
items,
|
||||
key: backend.id,
|
||||
kind: 'provider',
|
||||
label: backend.name
|
||||
});
|
||||
}
|
||||
|
||||
if (chatOnly.length) {
|
||||
ordered.push({
|
||||
backendId: null,
|
||||
isLocal: false,
|
||||
// one repo, one row per provider that serves it
|
||||
items: groupModelQuants(
|
||||
chatOnly.flatMap((entry) => entry.quants),
|
||||
true
|
||||
),
|
||||
key: 'oai-compat',
|
||||
kind: 'compat',
|
||||
label: 'OAI-compat'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const localItems = byBackend.get(LOCAL_BACKEND_ID);
|
||||
|
||||
if (localItems?.length) {
|
||||
ordered.push({
|
||||
backendId: LOCAL_BACKEND_ID,
|
||||
isLocal: true,
|
||||
items: localItems,
|
||||
key: LOCAL_BACKEND_ID,
|
||||
kind: 'local',
|
||||
label: 'Local models'
|
||||
});
|
||||
}
|
||||
|
||||
for (const backend of backendsStore.enabled) {
|
||||
if (backend.id === LOCAL_BACKEND_ID) continue;
|
||||
|
||||
const items = byBackend.get(backend.id);
|
||||
|
||||
if (items?.length) {
|
||||
ordered.push({
|
||||
backendId: backend.id,
|
||||
isLocal: false,
|
||||
items,
|
||||
key: backend.id,
|
||||
kind: 'provider',
|
||||
label: backend.name
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hidden.length) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import ModelsSelectorDownloadItem from './ModelsSelectorDownloadItem.svelte';
|
||||
import { Boxes, Heart, Power } from '@lucide/svelte';
|
||||
import { Heart, Power } from '@lucide/svelte';
|
||||
import { GroupedList, ModelAvatar, ModelsSelectorOption } from '$lib/components/app';
|
||||
import { ModelsSection } from '$lib/components/app';
|
||||
import { DialogConfirmDownload } from '$lib/components/app/dialogs';
|
||||
@@ -12,10 +12,7 @@
|
||||
} from '$lib/components/app/navigation/utils';
|
||||
import { LOCAL_BACKEND_ID, MODEL_ROW_WINDOW } from '$lib/constants';
|
||||
import { ModelDownloadConfirmAction } from '$lib/enums';
|
||||
import { ModelGroupingMode } from '$lib/enums/settings.enums';
|
||||
import { modelsStore, settingsStore } from '$lib/stores';
|
||||
import { getBackend } from '$lib/utils/api-base';
|
||||
import { getBackendCapabilities } from '$lib/utils/backend';
|
||||
import { groupModelFamilies, type ModelFamilyGroup } from '$lib/utils/model-families';
|
||||
|
||||
interface Props {
|
||||
@@ -89,29 +86,6 @@
|
||||
let headerClass = $derived(`${sectionHeaderClass} sticky z-10 bg-popover`);
|
||||
const headerStyle = 'top: var(--dropdown-sticky-height, 0px)';
|
||||
|
||||
/** By capability: one block whose models can load and unload, one that is chat only. */
|
||||
let compatSections = $derived.by(() => {
|
||||
const localItems = localGroups.available.flatMap((group) => group.items);
|
||||
const canLoad = (backendId: string) => getBackendCapabilities(getBackend(backendId)).loadUnload;
|
||||
const loadable = groups.providers.filter((provider) => canLoad(provider.backendId));
|
||||
const chatOnly = groups.providers.filter((provider) => !canLoad(provider.backendId));
|
||||
|
||||
return [
|
||||
{
|
||||
icon: 'logo' as const,
|
||||
items: [...localItems, ...loadable.flatMap((provider) => provider.items)],
|
||||
key: 'llama-compat',
|
||||
label: 'Llama-compat'
|
||||
},
|
||||
{
|
||||
icon: 'boxes' as const,
|
||||
items: chatOnly.flatMap((provider) => provider.items),
|
||||
key: 'oai-compat',
|
||||
label: 'OAI-compat'
|
||||
}
|
||||
].filter((section) => section.items.length > 0);
|
||||
});
|
||||
|
||||
/** In-flight / paused downloads, tracked by the status feed. */
|
||||
let getDownloadEntries = $derived(modelsStore.status.getDownloadEntries());
|
||||
|
||||
@@ -243,74 +217,49 @@
|
||||
{/if}
|
||||
{/snippet}
|
||||
|
||||
{#if settingsStore.config.modelGrouping === ModelGroupingMode.COMPAT}
|
||||
{#snippet compatSection(
|
||||
label: string,
|
||||
items: ModelItem[],
|
||||
iconKind: 'boxes' | 'logo',
|
||||
key: string
|
||||
)}
|
||||
<ModelsSection {label} persistKey={key} revealChevronOnHover sticky>
|
||||
{#snippet icon()}
|
||||
{#if iconKind === 'logo'}
|
||||
<Logo class="shrink-0" style="--size: 0.875rem" />
|
||||
{:else}
|
||||
<Boxes class="h-3.5 w-3.5 shrink-0" />
|
||||
{/if}
|
||||
{/snippet}
|
||||
{#if groups.loaded.length > 0 || groups.available.length > 0}
|
||||
<ModelsSection label="Local models" persistKey={LOCAL_BACKEND_ID} revealChevronOnHover sticky>
|
||||
{#snippet icon()}
|
||||
<Logo class="shrink-0" style="--size: 0.875rem" />
|
||||
{/snippet}
|
||||
|
||||
{@render listRows(items, key)}
|
||||
</ModelsSection>
|
||||
{/snippet}
|
||||
|
||||
{#each compatSections as section (section.key)}
|
||||
{@render compatSection(section.label, section.items, section.icon, section.key)}
|
||||
{/each}
|
||||
{:else}
|
||||
{#if groups.loaded.length > 0 || groups.available.length > 0}
|
||||
<ModelsSection label="Local models" persistKey={LOCAL_BACKEND_ID} revealChevronOnHover sticky>
|
||||
{#snippet icon()}
|
||||
<Logo class="shrink-0" style="--size: 0.875rem" />
|
||||
{/snippet}
|
||||
|
||||
{@render localRows()}
|
||||
</ModelsSection>
|
||||
{/if}
|
||||
|
||||
<!-- One section per remote provider. -->
|
||||
{#each groups.providers as provider (provider.backendId)}
|
||||
<ModelsSection
|
||||
backendId={provider.backendId}
|
||||
error={Boolean(provider.error)}
|
||||
label={provider.name}
|
||||
loading={provider.loading}
|
||||
onBack={onProviderBack}
|
||||
persistKey={provider.backendId}
|
||||
revealChevronOnHover
|
||||
sticky
|
||||
>
|
||||
{#if provider.items.length > 0}
|
||||
{@render listRows(provider.items, provider.backendId)}
|
||||
|
||||
{#if onProviderOpen && provider.matched > provider.items.length}
|
||||
<!-- same box as a model row, it opens the provider's full list -->
|
||||
<button
|
||||
class="flex w-full cursor-pointer items-center gap-2 rounded-sm p-2 text-left text-sm text-muted-foreground transition hover:bg-accent hover:text-foreground focus:outline-none"
|
||||
onclick={() => onProviderOpen(provider.backendId)}
|
||||
type="button"
|
||||
>
|
||||
+ {provider.matched - provider.items.length} more
|
||||
</button>
|
||||
{/if}
|
||||
{:else if provider.catalog === 0}
|
||||
<p class="px-4 pb-2 text-xs text-muted-foreground">
|
||||
{provider.error ?? (provider.loading ? 'Loading models...' : 'No models')}
|
||||
</p>
|
||||
{/if}
|
||||
</ModelsSection>
|
||||
{/each}
|
||||
{@render localRows()}
|
||||
</ModelsSection>
|
||||
{/if}
|
||||
|
||||
<!-- One section per remote provider. -->
|
||||
{#each groups.providers as provider (provider.backendId)}
|
||||
<ModelsSection
|
||||
backendId={provider.backendId}
|
||||
error={Boolean(provider.error)}
|
||||
label={provider.name}
|
||||
loading={provider.loading}
|
||||
onBack={onProviderBack}
|
||||
persistKey={provider.backendId}
|
||||
revealChevronOnHover
|
||||
sticky
|
||||
>
|
||||
{#if provider.items.length > 0}
|
||||
{@render listRows(provider.items, provider.backendId)}
|
||||
|
||||
{#if onProviderOpen && provider.matched > provider.items.length}
|
||||
<!-- same box as a model row, it opens the provider's full list -->
|
||||
<button
|
||||
class="flex w-full cursor-pointer items-center gap-2 rounded-sm p-2 text-left text-sm text-muted-foreground transition hover:bg-accent hover:text-foreground focus:outline-none"
|
||||
onclick={() => onProviderOpen(provider.backendId)}
|
||||
type="button"
|
||||
>
|
||||
+ {provider.matched - provider.items.length} more
|
||||
</button>
|
||||
{/if}
|
||||
{:else if provider.catalog === 0}
|
||||
<p class="px-4 pb-2 text-xs text-muted-foreground">
|
||||
{provider.error ?? (provider.loading ? 'Loading models...' : 'No models')}
|
||||
</p>
|
||||
{/if}
|
||||
</ModelsSection>
|
||||
{/each}
|
||||
|
||||
<DialogConfirmDownload
|
||||
action={ModelDownloadConfirmAction.CANCEL}
|
||||
onClose={() => (cancelOpen = false)}
|
||||
|
||||
@@ -42,7 +42,6 @@ export const SETTINGS_KEYS = {
|
||||
MENTION_SEARCH_MAX_DEPTH: 'mentionSearchMaxDepth',
|
||||
MIN_P: 'min_p',
|
||||
// Display
|
||||
MODEL_GROUPING: 'modelGrouping',
|
||||
PASTE_LONG_TEXT_TO_FILE_LEN: 'pasteLongTextToFileLen',
|
||||
PDF_AS_IMAGE: 'pdfAsImage',
|
||||
// Performance
|
||||
|
||||
@@ -4,21 +4,18 @@ import { SETTINGS_KEYS } from './settings-keys.constants';
|
||||
import { TITLE_GENERATION } from './title-generation.constants';
|
||||
import { FILE_GLOB_SEARCH_PICKERS } from './working-directory.constants';
|
||||
import {
|
||||
Boxes,
|
||||
Code,
|
||||
Database,
|
||||
Funnel,
|
||||
Layers,
|
||||
ListRestart,
|
||||
Monitor,
|
||||
Moon,
|
||||
PencilRuler,
|
||||
Server,
|
||||
SlidersVertical,
|
||||
Sun
|
||||
} from '@lucide/svelte';
|
||||
import { SyncableParameterType } from '$lib/enums';
|
||||
import { ModelGroupingMode, SettingsFieldType } from '$lib/enums/settings.enums';
|
||||
import { SettingsFieldType } from '$lib/enums/settings.enums';
|
||||
import { ColorMode } from '$lib/enums/ui.enums';
|
||||
import type {
|
||||
SettingsConfigValue,
|
||||
@@ -199,13 +196,6 @@ export const SETTINGS_REGISTRY: SettingsSectionEntry[] = [
|
||||
slug: SETTINGS_SECTION_SLUGS.GENERAL,
|
||||
title: SETTINGS_SECTION_TITLES.GENERAL
|
||||
},
|
||||
// Providers
|
||||
{
|
||||
icon: Server,
|
||||
settings: [],
|
||||
slug: SETTINGS_SECTION_SLUGS.BACKENDS,
|
||||
title: SETTINGS_SECTION_TITLES.BACKENDS
|
||||
},
|
||||
// Display
|
||||
{
|
||||
icon: Monitor,
|
||||
@@ -323,17 +313,6 @@ export const SETTINGS_REGISTRY: SettingsSectionEntry[] = [
|
||||
label: 'Show full path in mentions',
|
||||
type: SettingsFieldType.CHECKBOX
|
||||
},
|
||||
{
|
||||
defaultValue: ModelGroupingMode.PROVIDER,
|
||||
help: 'How the models manager groups its sections. One section per provider keeps every backend separate. By capability merges them into a llama-compat block, whose models can load and unload, and an OAI-compat block, which is chat only.',
|
||||
key: SETTINGS_KEYS.MODEL_GROUPING,
|
||||
label: 'Model grouping',
|
||||
options: [
|
||||
{ icon: Layers, label: 'One section per provider', value: ModelGroupingMode.PROVIDER },
|
||||
{ icon: Boxes, label: 'By capability', value: ModelGroupingMode.COMPAT }
|
||||
],
|
||||
type: SettingsFieldType.SELECT
|
||||
},
|
||||
{
|
||||
defaultValue: true,
|
||||
help: 'Group models into families (e.g. "Qwen") in the model picker and the models manager. Turn it off to list every model on its own.',
|
||||
|
||||
@@ -18,14 +18,6 @@ export enum SyncableParameterType {
|
||||
/**
|
||||
* Settings field type - defines the input type for settings fields
|
||||
*/
|
||||
/** How the models manager builds its sections below Loaded and Favorites. */
|
||||
export enum ModelGroupingMode {
|
||||
/** One llama-compat block and one OAI-compat block, families inside each. */
|
||||
COMPAT = 'compat',
|
||||
/** One section per provider, families inside each. */
|
||||
PROVIDER = 'provider'
|
||||
}
|
||||
|
||||
export enum SettingsFieldType {
|
||||
CHECKBOX = 'checkbox',
|
||||
INPUT = 'input',
|
||||
|
||||
Reference in New Issue
Block a user